tangled
alpha
login
or
join now
slices.network
/
slices
137
fork
atom
Highly ambitious ATProtocol AppView service and sdks
137
fork
atom
overview
issues
10
pulls
3
pipelines
add jetstream logs command
chadtmiller.com
5 months ago
054b4c38
b4803311
+107
2 changed files
expand all
collapse all
unified
split
packages
cli
src
commands
logs.ts
mod.ts
+101
packages/cli/src/commands/logs.ts
···
1
1
+
import { parseArgs } from "@std/cli/parse-args";
2
2
+
import { red, yellow, cyan, gray } from "@std/fmt/colors";
3
3
+
import { createAuthenticatedClient } from "../utils/client.ts";
4
4
+
import { logger } from "../utils/logger.ts";
5
5
+
import { SlicesConfigLoader, mergeConfig } from "../utils/config.ts";
6
6
+
7
7
+
function showLogsHelp() {
8
8
+
console.log(`
9
9
+
slices logs - View Jetstream logs for a slice
10
10
+
11
11
+
USAGE:
12
12
+
slices logs [OPTIONS]
13
13
+
14
14
+
OPTIONS:
15
15
+
--slice <SLICE_URI> Target slice URI (optional, or from slices.json)
16
16
+
--limit <NUMBER> Maximum number of log entries to return (default: 100, max: 1000)
17
17
+
--api-url <URL> Slices API base URL (default: https://api.slices.network or from slices.json)
18
18
+
-h, --help Show this help message
19
19
+
20
20
+
EXAMPLES:
21
21
+
slices logs --slice at://did:plc:example/slice
22
22
+
slices logs --limit 50
23
23
+
slices logs # Uses config from slices.json
24
24
+
`);
25
25
+
}
26
26
+
27
27
+
export async function logsCommand(commandArgs: unknown[], _globalArgs: Record<string, unknown>): Promise<void> {
28
28
+
const args = parseArgs(commandArgs as string[], {
29
29
+
boolean: ["help"],
30
30
+
string: ["slice", "api-url", "limit"],
31
31
+
alias: {
32
32
+
h: "help",
33
33
+
},
34
34
+
});
35
35
+
36
36
+
if (args.help) {
37
37
+
showLogsHelp();
38
38
+
return;
39
39
+
}
40
40
+
41
41
+
const configLoader = new SlicesConfigLoader();
42
42
+
const slicesConfig = await configLoader.load();
43
43
+
const mergedConfig = mergeConfig(slicesConfig, args);
44
44
+
45
45
+
const sliceUri = mergedConfig.slice;
46
46
+
const apiUrl = mergedConfig.apiUrl || "https://api.slices.network";
47
47
+
const limit = args.limit ? parseInt(args.limit as string, 10) : 100;
48
48
+
49
49
+
if (isNaN(limit) || limit < 1 || limit > 1000) {
50
50
+
logger.error("--limit must be a number between 1 and 1000");
51
51
+
Deno.exit(1);
52
52
+
}
53
53
+
54
54
+
try {
55
55
+
const client = await createAuthenticatedClient(sliceUri || "", apiUrl);
56
56
+
57
57
+
const response = await client.network.slices.slice.getJetstreamLogs({
58
58
+
slice: sliceUri,
59
59
+
limit,
60
60
+
});
61
61
+
62
62
+
if (response.logs.length === 0) {
63
63
+
logger.info("No logs found");
64
64
+
return;
65
65
+
}
66
66
+
67
67
+
logger.section(`Jetstream Logs (${response.logs.length} entries)`);
68
68
+
69
69
+
for (const log of response.logs) {
70
70
+
const timestamp = new Date(log.createdAt).toLocaleString();
71
71
+
const level = log.level.toUpperCase().padEnd(5);
72
72
+
const coloredLevel = colorizeLevel(level, log.level);
73
73
+
74
74
+
console.log(`${timestamp} ${coloredLevel} ${log.message}`);
75
75
+
76
76
+
if (log.metadata && Object.keys(log.metadata).length > 0) {
77
77
+
console.log(` ${gray(JSON.stringify(log.metadata))}`);
78
78
+
}
79
79
+
}
80
80
+
81
81
+
} catch (error) {
82
82
+
const err = error as Error;
83
83
+
logger.error(`Failed to fetch logs: ${err.message}`);
84
84
+
Deno.exit(1);
85
85
+
}
86
86
+
}
87
87
+
88
88
+
function colorizeLevel(levelText: string, level: string): string {
89
89
+
switch (level.toLowerCase()) {
90
90
+
case "error":
91
91
+
return red(levelText);
92
92
+
case "warn":
93
93
+
return yellow(levelText);
94
94
+
case "info":
95
95
+
return cyan(levelText);
96
96
+
case "debug":
97
97
+
return gray(levelText);
98
98
+
default:
99
99
+
return levelText;
100
100
+
}
101
101
+
}
+6
packages/cli/src/mod.ts
···
7
7
import { statusCommand } from "./commands/status.ts";
8
8
import { codegenCommand } from "./commands/codegen.ts";
9
9
import { initCommand } from "./commands/init.ts";
10
10
+
import { logsCommand } from "./commands/logs.ts";
10
11
11
12
const VERSION = "0.1.0";
12
13
···
23
24
lexicon Manage lexicons (push, pull, list)
24
25
codegen Generate TypeScript client from lexicon files
25
26
status Show authentication and configuration status
27
27
+
logs View Jetstream logs for a slice
26
28
help Show this help message
27
29
28
30
OPTIONS:
···
36
38
slices lexicon push --path ./lexicons --slice at://did:plc:example/slice
37
39
slices lexicon list --slice at://did:plc:example/slice
38
40
slices status
41
41
+
slices logs --slice at://did:plc:example/slice
39
42
`);
40
43
}
41
44
···
88
91
break;
89
92
case "status":
90
93
await statusCommand(commandArgs, args);
94
94
+
break;
95
95
+
case "logs":
96
96
+
await logsCommand(commandArgs, args);
91
97
break;
92
98
case "help":
93
99
showHelp();