@hasna/logs 0.3.3 → 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 +25 -19
- package/package.json +1 -1
- package/src/cli/index.ts +26 -20
package/dist/cli/index.js
CHANGED
|
@@ -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 {
|
|
@@ -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,38 +2204,38 @@ 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);
|
|
@@ -2302,12 +2308,12 @@ Errors: ${errorCount} Warnings: ${warnCount}`);
|
|
|
2302
2308
|
process.exit(0);
|
|
2303
2309
|
});
|
|
2304
2310
|
});
|
|
2305
|
-
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) => {
|
|
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) => {
|
|
2306
2312
|
const { exportToCsv, exportToJson } = await import("../export-c3eqjste.js");
|
|
2307
2313
|
const { createWriteStream } = await import("fs");
|
|
2308
2314
|
const db = getDb();
|
|
2309
2315
|
const options = {
|
|
2310
|
-
project_id: opts.project,
|
|
2316
|
+
project_id: resolveProject(opts.project),
|
|
2311
2317
|
since: parseRelativeTime(opts.since),
|
|
2312
2318
|
level: opts.level,
|
|
2313
2319
|
service: opts.service,
|
package/package.json
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -5,10 +5,16 @@ import { ingestLog } from "../lib/ingest.ts"
|
|
|
5
5
|
import { searchLogs, tailLogs } from "../lib/query.ts"
|
|
6
6
|
import { summarizeLogs } from "../lib/summarize.ts"
|
|
7
7
|
import { createJob, listJobs } from "../lib/jobs.ts"
|
|
8
|
-
import { createPage, createProject, listPages, listProjects } from "../lib/projects.ts"
|
|
8
|
+
import { createPage, createProject, listPages, listProjects, resolveProjectId } from "../lib/projects.ts"
|
|
9
9
|
import { runJob } from "../lib/scheduler.ts"
|
|
10
10
|
import type { LogLevel } from "../types/index.ts"
|
|
11
11
|
|
|
12
|
+
/** Resolve a project name or ID from CLI --project flag */
|
|
13
|
+
function resolveProject(nameOrId: string | undefined): string | undefined {
|
|
14
|
+
if (!nameOrId) return undefined;
|
|
15
|
+
return resolveProjectId(getDb(), nameOrId) ?? nameOrId;
|
|
16
|
+
}
|
|
17
|
+
|
|
12
18
|
const program = new Command()
|
|
13
19
|
.name("logs")
|
|
14
20
|
.description("@hasna/logs — log aggregation and monitoring")
|
|
@@ -17,7 +23,7 @@ const program = new Command()
|
|
|
17
23
|
// ── logs list ──────────────────────────────────────────────
|
|
18
24
|
program.command("list")
|
|
19
25
|
.description("Search and list logs")
|
|
20
|
-
.option("--project <id>", "Filter by project ID")
|
|
26
|
+
.option("--project <name|id>", "Filter by project name or ID")
|
|
21
27
|
.option("--page <id>", "Filter by page ID")
|
|
22
28
|
.option("--level <levels>", "Comma-separated levels (error,warn,info,debug,fatal)")
|
|
23
29
|
.option("--service <name>", "Filter by service")
|
|
@@ -29,7 +35,7 @@ program.command("list")
|
|
|
29
35
|
const db = getDb()
|
|
30
36
|
const since = parseRelativeTime(opts.since)
|
|
31
37
|
const rows = searchLogs(db, {
|
|
32
|
-
project_id: opts.project,
|
|
38
|
+
project_id: resolveProject(opts.project),
|
|
33
39
|
page_id: opts.page,
|
|
34
40
|
level: opts.level ? (opts.level.split(",") as LogLevel[]) : undefined,
|
|
35
41
|
service: opts.service,
|
|
@@ -52,20 +58,20 @@ program.command("list")
|
|
|
52
58
|
// ── logs tail ──────────────────────────────────────────────
|
|
53
59
|
program.command("tail")
|
|
54
60
|
.description("Show most recent logs")
|
|
55
|
-
.option("--project <id>")
|
|
61
|
+
.option("--project <name|id>", "Project name or ID")
|
|
56
62
|
.option("--n <count>", "Number of logs", "50")
|
|
57
63
|
.action((opts) => {
|
|
58
|
-
const rows = tailLogs(getDb(), opts.project, Number(opts.n))
|
|
64
|
+
const rows = tailLogs(getDb(), resolveProject(opts.project), Number(opts.n))
|
|
59
65
|
for (const r of rows) console.log(`${r.timestamp} ${pad(r.level.toUpperCase(), 5)} ${r.message}`)
|
|
60
66
|
})
|
|
61
67
|
|
|
62
68
|
// ── logs summary ──────────────────────────────────────────
|
|
63
69
|
program.command("summary")
|
|
64
70
|
.description("Error/warn summary by service")
|
|
65
|
-
.option("--project <id>")
|
|
71
|
+
.option("--project <name|id>", "Project name or ID")
|
|
66
72
|
.option("--since <time>", "Relative time (1h, 24h, 7d)", "24h")
|
|
67
73
|
.action((opts) => {
|
|
68
|
-
const summary = summarizeLogs(getDb(), opts.project, parseRelativeTime(opts.since))
|
|
74
|
+
const summary = summarizeLogs(getDb(), resolveProject(opts.project), parseRelativeTime(opts.since))
|
|
69
75
|
if (!summary.length) { console.log("No errors/warnings in this window."); return }
|
|
70
76
|
for (const s of summary) console.log(`${pad(s.level.toUpperCase(), 5)} ${pad(s.service ?? "-", 15)} count=${s.count} latest=${s.latest}`)
|
|
71
77
|
})
|
|
@@ -75,10 +81,10 @@ program.command("push <message>")
|
|
|
75
81
|
.description("Push a log entry")
|
|
76
82
|
.option("--level <level>", "Log level", "info")
|
|
77
83
|
.option("--service <name>")
|
|
78
|
-
.option("--project <id>")
|
|
84
|
+
.option("--project <name|id>", "Project name or ID")
|
|
79
85
|
.option("--trace <id>", "Trace ID")
|
|
80
86
|
.action((message, opts) => {
|
|
81
|
-
const row = ingestLog(getDb(), { level: opts.level as LogLevel, message, service: opts.service, project_id: opts.project, trace_id: opts.trace })
|
|
87
|
+
const row = ingestLog(getDb(), { level: opts.level as LogLevel, message, service: opts.service, project_id: resolveProject(opts.project), trace_id: opts.trace })
|
|
82
88
|
console.log(`Logged: ${row.id}`)
|
|
83
89
|
})
|
|
84
90
|
|
|
@@ -104,18 +110,18 @@ projectCmd.command("list").action(() => {
|
|
|
104
110
|
const pageCmd = program.command("page").description("Manage pages")
|
|
105
111
|
|
|
106
112
|
pageCmd.command("add")
|
|
107
|
-
.option("--project <id>")
|
|
113
|
+
.option("--project <name|id>", "Project name or ID")
|
|
108
114
|
.option("--url <url>")
|
|
109
115
|
.option("--name <name>")
|
|
110
116
|
.action((opts) => {
|
|
111
117
|
if (!opts.project || !opts.url) { console.error("--project and --url required"); process.exit(1) }
|
|
112
|
-
const p = createPage(getDb(), { project_id: opts.project, url: opts.url, name: opts.name })
|
|
118
|
+
const p = createPage(getDb(), { project_id: resolveProject(opts.project), url: opts.url, name: opts.name })
|
|
113
119
|
console.log(`Page registered: ${p.id} — ${p.url}`)
|
|
114
120
|
})
|
|
115
121
|
|
|
116
|
-
pageCmd.command("list").option("--project <id>").action((opts) => {
|
|
122
|
+
pageCmd.command("list").option("--project <name|id>", "Project name or ID").action((opts) => {
|
|
117
123
|
if (!opts.project) { console.error("--project required"); process.exit(1) }
|
|
118
|
-
const pages = listPages(getDb(), opts.project)
|
|
124
|
+
const pages = listPages(getDb(), resolveProject(opts.project))
|
|
119
125
|
for (const p of pages) console.log(`${p.id} ${p.url} last=${p.last_scanned_at ?? "never"}`)
|
|
120
126
|
})
|
|
121
127
|
|
|
@@ -123,16 +129,16 @@ pageCmd.command("list").option("--project <id>").action((opts) => {
|
|
|
123
129
|
const jobCmd = program.command("job").description("Manage scan jobs")
|
|
124
130
|
|
|
125
131
|
jobCmd.command("create")
|
|
126
|
-
.option("--project <id>")
|
|
132
|
+
.option("--project <name|id>", "Project name or ID")
|
|
127
133
|
.option("--schedule <cron>", "Cron expression", "*/30 * * * *")
|
|
128
134
|
.action((opts) => {
|
|
129
135
|
if (!opts.project) { console.error("--project required"); process.exit(1) }
|
|
130
|
-
const j = createJob(getDb(), { project_id: opts.project, schedule: opts.schedule })
|
|
136
|
+
const j = createJob(getDb(), { project_id: resolveProject(opts.project), schedule: opts.schedule })
|
|
131
137
|
console.log(`Job created: ${j.id} — ${j.schedule}`)
|
|
132
138
|
})
|
|
133
139
|
|
|
134
|
-
jobCmd.command("list").option("--project <id>").action((opts) => {
|
|
135
|
-
const jobs = listJobs(getDb(), opts.project)
|
|
140
|
+
jobCmd.command("list").option("--project <name|id>", "Project name or ID").action((opts) => {
|
|
141
|
+
const jobs = listJobs(getDb(), resolveProject(opts.project))
|
|
136
142
|
for (const j of jobs) console.log(`${j.id} ${j.schedule} enabled=${j.enabled} last=${j.last_run_at ?? "never"}`)
|
|
137
143
|
})
|
|
138
144
|
|
|
@@ -140,7 +146,7 @@ jobCmd.command("list").option("--project <id>").action((opts) => {
|
|
|
140
146
|
program.command("scan")
|
|
141
147
|
.description("Run an immediate scan for a job")
|
|
142
148
|
.option("--job <id>")
|
|
143
|
-
.option("--project <id>")
|
|
149
|
+
.option("--project <name|id>", "Project name or ID")
|
|
144
150
|
.action(async (opts) => {
|
|
145
151
|
if (!opts.job) { console.error("--job required"); process.exit(1) }
|
|
146
152
|
const db = getDb()
|
|
@@ -216,7 +222,7 @@ program.command("watch")
|
|
|
216
222
|
// ── logs export ───────────────────────────────────────────
|
|
217
223
|
program.command("export")
|
|
218
224
|
.description("Export logs to JSON or CSV")
|
|
219
|
-
.option("--project <id>")
|
|
225
|
+
.option("--project <name|id>", "Project name or ID")
|
|
220
226
|
.option("--since <time>", "Relative time or ISO")
|
|
221
227
|
.option("--level <level>")
|
|
222
228
|
.option("--service <name>")
|
|
@@ -228,7 +234,7 @@ program.command("export")
|
|
|
228
234
|
const { createWriteStream } = await import("node:fs")
|
|
229
235
|
const db = getDb()
|
|
230
236
|
const options = {
|
|
231
|
-
project_id: opts.project,
|
|
237
|
+
project_id: resolveProject(opts.project),
|
|
232
238
|
since: parseRelativeTime(opts.since),
|
|
233
239
|
level: opts.level,
|
|
234
240
|
service: opts.service,
|