@hasna/logs 0.3.2 → 0.3.4
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/cli/index.js +43 -30
- package/dist/export-c3eqjste.js +10 -0
- package/dist/health-9792c1rc.js +8 -0
- package/dist/index-fzmz9aqs.js +1241 -0
- package/dist/index-re3ntm60.js +48 -0
- package/dist/index-xjn8gam3.js +39 -0
- package/dist/jobs-ypmmc2ma.js +22 -0
- package/dist/mcp/index.js +2 -2
- package/dist/query-shjjj67k.js +14 -0
- package/dist/server/index.js +3 -3
- package/package.json +1 -1
- package/src/cli/index.ts +43 -27
package/dist/cli/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
import {
|
|
4
4
|
runJob
|
|
5
|
-
} from "../index-
|
|
5
|
+
} from "../index-fzmz9aqs.js";
|
|
6
6
|
import {
|
|
7
7
|
createPage,
|
|
8
8
|
createProject,
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
ingestLog,
|
|
11
11
|
listPages,
|
|
12
12
|
listProjects,
|
|
13
|
+
resolveProjectId,
|
|
13
14
|
summarizeLogs
|
|
14
15
|
} from "../index-5tvnhvgr.js";
|
|
15
16
|
import {
|
|
@@ -24,7 +25,7 @@ import {
|
|
|
24
25
|
__commonJS,
|
|
25
26
|
__require,
|
|
26
27
|
__toESM
|
|
27
|
-
} from "../index-
|
|
28
|
+
} from "../index-re3ntm60.js";
|
|
28
29
|
|
|
29
30
|
// node_modules/commander/lib/error.js
|
|
30
31
|
var require_error = __commonJS((exports) => {
|
|
@@ -2136,12 +2137,17 @@ var {
|
|
|
2136
2137
|
} = import__.default;
|
|
2137
2138
|
|
|
2138
2139
|
// src/cli/index.ts
|
|
2140
|
+
function resolveProject(nameOrId) {
|
|
2141
|
+
if (!nameOrId)
|
|
2142
|
+
return;
|
|
2143
|
+
return resolveProjectId(getDb(), nameOrId) ?? nameOrId;
|
|
2144
|
+
}
|
|
2139
2145
|
var program2 = new Command().name("logs").description("@hasna/logs \u2014 log aggregation and monitoring").version("0.0.1");
|
|
2140
|
-
program2.command("list").description("Search and list logs").option("--project <id>", "Filter by project ID").option("--page <id>", "Filter by page ID").option("--level <levels>", "Comma-separated levels (error,warn,info,debug,fatal)").option("--service <name>", "Filter by service").option("--since <iso>", "Since timestamp or relative (1h, 24h, 7d)").option("--text <query>", "Full-text search").option("--limit <n>", "Max results", "100").option("--format <fmt>", "Output format: table|json|compact", "table").action((opts) => {
|
|
2146
|
+
program2.command("list").description("Search and list logs").option("--project <name|id>", "Filter by project name or ID").option("--page <id>", "Filter by page ID").option("--level <levels>", "Comma-separated levels (error,warn,info,debug,fatal)").option("--service <name>", "Filter by service").option("--since <iso>", "Since timestamp or relative (1h, 24h, 7d)").option("--text <query>", "Full-text search").option("--limit <n>", "Max results", "100").option("--format <fmt>", "Output format: table|json|compact", "table").action((opts) => {
|
|
2141
2147
|
const db = getDb();
|
|
2142
2148
|
const since = parseRelativeTime(opts.since);
|
|
2143
2149
|
const rows = searchLogs(db, {
|
|
2144
|
-
project_id: opts.project,
|
|
2150
|
+
project_id: resolveProject(opts.project),
|
|
2145
2151
|
page_id: opts.page,
|
|
2146
2152
|
level: opts.level ? opts.level.split(",") : undefined,
|
|
2147
2153
|
service: opts.service,
|
|
@@ -2165,13 +2171,13 @@ program2.command("list").description("Search and list logs").option("--project <
|
|
|
2165
2171
|
console.log(`
|
|
2166
2172
|
${rows.length} log(s)`);
|
|
2167
2173
|
});
|
|
2168
|
-
program2.command("tail").description("Show most recent logs").option("--project <id>").option("--n <count>", "Number of logs", "50").action((opts) => {
|
|
2169
|
-
const rows = tailLogs(getDb(), opts.project, Number(opts.n));
|
|
2174
|
+
program2.command("tail").description("Show most recent logs").option("--project <name|id>", "Project name or ID").option("--n <count>", "Number of logs", "50").action((opts) => {
|
|
2175
|
+
const rows = tailLogs(getDb(), resolveProject(opts.project), Number(opts.n));
|
|
2170
2176
|
for (const r of rows)
|
|
2171
2177
|
console.log(`${r.timestamp} ${pad(r.level.toUpperCase(), 5)} ${r.message}`);
|
|
2172
2178
|
});
|
|
2173
|
-
program2.command("summary").description("Error/warn summary by service").option("--project <id>").option("--since <time>", "Relative time (1h, 24h, 7d)", "24h").action((opts) => {
|
|
2174
|
-
const summary = summarizeLogs(getDb(), opts.project, parseRelativeTime(opts.since));
|
|
2179
|
+
program2.command("summary").description("Error/warn summary by service").option("--project <name|id>", "Project name or ID").option("--since <time>", "Relative time (1h, 24h, 7d)", "24h").action((opts) => {
|
|
2180
|
+
const summary = summarizeLogs(getDb(), resolveProject(opts.project), parseRelativeTime(opts.since));
|
|
2175
2181
|
if (!summary.length) {
|
|
2176
2182
|
console.log("No errors/warnings in this window.");
|
|
2177
2183
|
return;
|
|
@@ -2179,8 +2185,8 @@ program2.command("summary").description("Error/warn summary by service").option(
|
|
|
2179
2185
|
for (const s of summary)
|
|
2180
2186
|
console.log(`${pad(s.level.toUpperCase(), 5)} ${pad(s.service ?? "-", 15)} count=${s.count} latest=${s.latest}`);
|
|
2181
2187
|
});
|
|
2182
|
-
program2.command("push <message>").description("Push a log entry").option("--level <level>", "Log level", "info").option("--service <name>").option("--project <id>").option("--trace <id>", "Trace ID").action((message, opts) => {
|
|
2183
|
-
const row = ingestLog(getDb(), { level: opts.level, message, service: opts.service, project_id: opts.project, trace_id: opts.trace });
|
|
2188
|
+
program2.command("push <message>").description("Push a log entry").option("--level <level>", "Log level", "info").option("--service <name>").option("--project <name|id>", "Project name or ID").option("--trace <id>", "Trace ID").action((message, opts) => {
|
|
2189
|
+
const row = ingestLog(getDb(), { level: opts.level, message, service: opts.service, project_id: resolveProject(opts.project), trace_id: opts.trace });
|
|
2184
2190
|
console.log(`Logged: ${row.id}`);
|
|
2185
2191
|
});
|
|
2186
2192
|
var projectCmd = program2.command("project").description("Manage projects");
|
|
@@ -2198,44 +2204,44 @@ projectCmd.command("list").action(() => {
|
|
|
2198
2204
|
console.log(`${p.id} ${p.name} ${p.base_url ?? ""} ${p.github_repo ?? ""}`);
|
|
2199
2205
|
});
|
|
2200
2206
|
var pageCmd = program2.command("page").description("Manage pages");
|
|
2201
|
-
pageCmd.command("add").option("--project <id>").option("--url <url>").option("--name <name>").action((opts) => {
|
|
2207
|
+
pageCmd.command("add").option("--project <name|id>", "Project name or ID").option("--url <url>").option("--name <name>").action((opts) => {
|
|
2202
2208
|
if (!opts.project || !opts.url) {
|
|
2203
2209
|
console.error("--project and --url required");
|
|
2204
2210
|
process.exit(1);
|
|
2205
2211
|
}
|
|
2206
|
-
const p = createPage(getDb(), { project_id: opts.project, url: opts.url, name: opts.name });
|
|
2212
|
+
const p = createPage(getDb(), { project_id: resolveProject(opts.project), url: opts.url, name: opts.name });
|
|
2207
2213
|
console.log(`Page registered: ${p.id} \u2014 ${p.url}`);
|
|
2208
2214
|
});
|
|
2209
|
-
pageCmd.command("list").option("--project <id>").action((opts) => {
|
|
2215
|
+
pageCmd.command("list").option("--project <name|id>", "Project name or ID").action((opts) => {
|
|
2210
2216
|
if (!opts.project) {
|
|
2211
2217
|
console.error("--project required");
|
|
2212
2218
|
process.exit(1);
|
|
2213
2219
|
}
|
|
2214
|
-
const pages = listPages(getDb(), opts.project);
|
|
2220
|
+
const pages = listPages(getDb(), resolveProject(opts.project));
|
|
2215
2221
|
for (const p of pages)
|
|
2216
2222
|
console.log(`${p.id} ${p.url} last=${p.last_scanned_at ?? "never"}`);
|
|
2217
2223
|
});
|
|
2218
2224
|
var jobCmd = program2.command("job").description("Manage scan jobs");
|
|
2219
|
-
jobCmd.command("create").option("--project <id>").option("--schedule <cron>", "Cron expression", "*/30 * * * *").action((opts) => {
|
|
2225
|
+
jobCmd.command("create").option("--project <name|id>", "Project name or ID").option("--schedule <cron>", "Cron expression", "*/30 * * * *").action((opts) => {
|
|
2220
2226
|
if (!opts.project) {
|
|
2221
2227
|
console.error("--project required");
|
|
2222
2228
|
process.exit(1);
|
|
2223
2229
|
}
|
|
2224
|
-
const j = createJob(getDb(), { project_id: opts.project, schedule: opts.schedule });
|
|
2230
|
+
const j = createJob(getDb(), { project_id: resolveProject(opts.project), schedule: opts.schedule });
|
|
2225
2231
|
console.log(`Job created: ${j.id} \u2014 ${j.schedule}`);
|
|
2226
2232
|
});
|
|
2227
|
-
jobCmd.command("list").option("--project <id>").action((opts) => {
|
|
2228
|
-
const jobs = listJobs(getDb(), opts.project);
|
|
2233
|
+
jobCmd.command("list").option("--project <name|id>", "Project name or ID").action((opts) => {
|
|
2234
|
+
const jobs = listJobs(getDb(), resolveProject(opts.project));
|
|
2229
2235
|
for (const j of jobs)
|
|
2230
2236
|
console.log(`${j.id} ${j.schedule} enabled=${j.enabled} last=${j.last_run_at ?? "never"}`);
|
|
2231
2237
|
});
|
|
2232
|
-
program2.command("scan").description("Run an immediate scan for a job").option("--job <id>").option("--project <id>").action(async (opts) => {
|
|
2238
|
+
program2.command("scan").description("Run an immediate scan for a job").option("--job <id>").option("--project <name|id>", "Project name or ID").action(async (opts) => {
|
|
2233
2239
|
if (!opts.job) {
|
|
2234
2240
|
console.error("--job required");
|
|
2235
2241
|
process.exit(1);
|
|
2236
2242
|
}
|
|
2237
2243
|
const db = getDb();
|
|
2238
|
-
const job = (await import("../jobs-
|
|
2244
|
+
const job = (await import("../jobs-ypmmc2ma.js")).getJob(db, opts.job);
|
|
2239
2245
|
if (!job) {
|
|
2240
2246
|
console.error("Job not found");
|
|
2241
2247
|
process.exit(1);
|
|
@@ -2244,9 +2250,15 @@ program2.command("scan").description("Run an immediate scan for a job").option("
|
|
|
2244
2250
|
await runJob(db, job.id, job.project_id, job.page_id ?? undefined);
|
|
2245
2251
|
console.log("Scan complete.");
|
|
2246
2252
|
});
|
|
2247
|
-
program2.command("watch").description("Stream new logs in real time with color coding").option("--project <id>").option("--level <levels>", "Comma-separated levels").option("--service <name>").action(async (opts) => {
|
|
2253
|
+
program2.command("watch").description("Stream new logs in real time with color coding").option("--project <name|id>", "Filter by project name or ID").option("--level <levels>", "Comma-separated levels (debug,info,warn,error,fatal)").option("--service <name>", "Filter by service name").option("--interval <ms>", "Poll interval in milliseconds (default: 500)", "500").option("--since <time>", "Start from this time (default: now)").action(async (opts) => {
|
|
2248
2254
|
const db = getDb();
|
|
2249
|
-
const { searchLogs: searchLogs2 } = await import("../query-
|
|
2255
|
+
const { searchLogs: searchLogs2 } = await import("../query-shjjj67k.js");
|
|
2256
|
+
let projectId = opts.project;
|
|
2257
|
+
if (projectId) {
|
|
2258
|
+
const proj = db.query("SELECT id FROM projects WHERE id = ? OR name = ?").get(projectId, projectId);
|
|
2259
|
+
if (proj)
|
|
2260
|
+
projectId = proj.id;
|
|
2261
|
+
}
|
|
2250
2262
|
const COLORS = {
|
|
2251
2263
|
debug: "\x1B[90m",
|
|
2252
2264
|
info: "\x1B[36m",
|
|
@@ -2256,15 +2268,16 @@ program2.command("watch").description("Stream new logs in real time with color c
|
|
|
2256
2268
|
};
|
|
2257
2269
|
const RESET = "\x1B[0m";
|
|
2258
2270
|
const BOLD = "\x1B[1m";
|
|
2259
|
-
let lastTimestamp = new Date().toISOString();
|
|
2271
|
+
let lastTimestamp = opts.since ? new Date(opts.since).toISOString() : new Date().toISOString();
|
|
2260
2272
|
let errorCount = 0;
|
|
2261
2273
|
let warnCount = 0;
|
|
2274
|
+
const pollIntervalMs = Math.max(100, Number(opts.interval) || 500);
|
|
2262
2275
|
process.stdout.write(`\x1B[2J\x1B[H`);
|
|
2263
|
-
console.log(`${BOLD}@hasna/logs watch${RESET} \u2014 Ctrl+C to exit
|
|
2276
|
+
console.log(`${BOLD}@hasna/logs watch${RESET} \u2014 Ctrl+C to exit${projectId ? ` [project: ${opts.project}]` : ""}
|
|
2264
2277
|
`);
|
|
2265
2278
|
const poll = () => {
|
|
2266
2279
|
const rows = searchLogs2(db, {
|
|
2267
|
-
project_id:
|
|
2280
|
+
project_id: projectId,
|
|
2268
2281
|
level: opts.level ? opts.level.split(",") : undefined,
|
|
2269
2282
|
service: opts.service,
|
|
2270
2283
|
since: lastTimestamp,
|
|
@@ -2286,7 +2299,7 @@ program2.command("watch").description("Stream new logs in real time with color c
|
|
|
2286
2299
|
}
|
|
2287
2300
|
process.stdout.write(`\x1B]2;logs: ${errorCount}E ${warnCount}W\x07`);
|
|
2288
2301
|
};
|
|
2289
|
-
const interval = setInterval(poll,
|
|
2302
|
+
const interval = setInterval(poll, pollIntervalMs);
|
|
2290
2303
|
process.on("SIGINT", () => {
|
|
2291
2304
|
clearInterval(interval);
|
|
2292
2305
|
console.log(`
|
|
@@ -2295,12 +2308,12 @@ Errors: ${errorCount} Warnings: ${warnCount}`);
|
|
|
2295
2308
|
process.exit(0);
|
|
2296
2309
|
});
|
|
2297
2310
|
});
|
|
2298
|
-
program2.command("export").description("Export logs to JSON or CSV").option("--project <id>").option("--since <time>", "Relative time or ISO").option("--level <level>").option("--service <name>").option("--format <fmt>", "json or csv", "json").option("--output <file>", "Output file (default: stdout)").option("--limit <n>", "Max rows", "100000").action(async (opts) => {
|
|
2299
|
-
const { exportToCsv, exportToJson } = await import("../export-
|
|
2311
|
+
program2.command("export").description("Export logs to JSON or CSV").option("--project <name|id>", "Project name or ID").option("--since <time>", "Relative time or ISO").option("--level <level>").option("--service <name>").option("--format <fmt>", "json or csv", "json").option("--output <file>", "Output file (default: stdout)").option("--limit <n>", "Max rows", "100000").action(async (opts) => {
|
|
2312
|
+
const { exportToCsv, exportToJson } = await import("../export-c3eqjste.js");
|
|
2300
2313
|
const { createWriteStream } = await import("fs");
|
|
2301
2314
|
const db = getDb();
|
|
2302
2315
|
const options = {
|
|
2303
|
-
project_id: opts.project,
|
|
2316
|
+
project_id: resolveProject(opts.project),
|
|
2304
2317
|
since: parseRelativeTime(opts.since),
|
|
2305
2318
|
level: opts.level,
|
|
2306
2319
|
service: opts.service,
|
|
@@ -2322,7 +2335,7 @@ Exported ${count} log(s)
|
|
|
2322
2335
|
}
|
|
2323
2336
|
});
|
|
2324
2337
|
program2.command("health").description("Show server health and DB stats").action(async () => {
|
|
2325
|
-
const { getHealth } = await import("../health-
|
|
2338
|
+
const { getHealth } = await import("../health-9792c1rc.js");
|
|
2326
2339
|
const h = getHealth(getDb());
|
|
2327
2340
|
console.log(JSON.stringify(h, null, 2));
|
|
2328
2341
|
});
|