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