log -f
This commit is contained in:
parent
e1b53fc54d
commit
84a341ebf9
|
|
@ -57,7 +57,15 @@ const restartApp = async (app: string) => {
|
||||||
await post(`/api/apps/${app}/restart`)
|
await post(`/api/apps/${app}/restart`)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function logApp(name: string) {
|
const printLog = (line: LogLine) =>
|
||||||
|
console.log(`${new Date(line.time).toLocaleTimeString()} ${line.text}`)
|
||||||
|
|
||||||
|
async function logApp(name: string, options: { follow?: boolean }) {
|
||||||
|
if (options.follow) {
|
||||||
|
await tailLogs(name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const logs: LogLine[] | undefined = await get(`/api/apps/${name}/logs`)
|
const logs: LogLine[] | undefined = await get(`/api/apps/${name}/logs`)
|
||||||
if (!logs) {
|
if (!logs) {
|
||||||
console.error(`App not found: ${name}`)
|
console.error(`App not found: ${name}`)
|
||||||
|
|
@ -68,8 +76,37 @@ async function logApp(name: string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for (const line of logs) {
|
for (const line of logs) {
|
||||||
const time = new Date(line.time).toLocaleTimeString()
|
printLog(line)
|
||||||
console.log(`${time} ${line.text}`)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function tailLogs(name: string) {
|
||||||
|
const url = join(HOST, `/api/apps/${name}/logs/stream`)
|
||||||
|
const res = await fetch(url)
|
||||||
|
if (!res.ok) {
|
||||||
|
console.error(`App not found: ${name}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!res.body) return
|
||||||
|
|
||||||
|
const reader = res.body.getReader()
|
||||||
|
const decoder = new TextDecoder()
|
||||||
|
let buffer = ''
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const { done, value } = await reader.read()
|
||||||
|
if (done) break
|
||||||
|
|
||||||
|
buffer += decoder.decode(value, { stream: true })
|
||||||
|
const lines = buffer.split('\n\n')
|
||||||
|
buffer = lines.pop() ?? ''
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
if (line.startsWith('data: ')) {
|
||||||
|
const data = JSON.parse(line.slice(6)) as LogLine
|
||||||
|
printLog(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,11 +156,13 @@ program
|
||||||
.command('logs')
|
.command('logs')
|
||||||
.description('Show logs for an app')
|
.description('Show logs for an app')
|
||||||
.argument('<name>', 'app name')
|
.argument('<name>', 'app name')
|
||||||
|
.option('-f, --follow', 'follow log output')
|
||||||
.action(logApp)
|
.action(logApp)
|
||||||
|
|
||||||
program
|
program
|
||||||
.command('log', { hidden: true })
|
.command('log', { hidden: true })
|
||||||
.argument('<name>', 'app name')
|
.argument('<name>', 'app name')
|
||||||
|
.option('-f, --follow', 'follow log output')
|
||||||
.action(logApp)
|
.action(logApp)
|
||||||
|
|
||||||
program
|
program
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,31 @@ app.get('/api/apps/:app/logs', c => {
|
||||||
return c.json(app.logs ?? [])
|
return c.json(app.logs ?? [])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
app.sse('/api/apps/:app/logs/stream', (send, c) => {
|
||||||
|
const appName = c.req.param('app')
|
||||||
|
const targetApp = allApps().find(a => a.name === appName)
|
||||||
|
if (!targetApp) return
|
||||||
|
|
||||||
|
let lastLogCount = 0
|
||||||
|
|
||||||
|
const sendNewLogs = () => {
|
||||||
|
const currentApp = allApps().find(a => a.name === appName)
|
||||||
|
if (!currentApp) return
|
||||||
|
|
||||||
|
const logs = currentApp.logs ?? []
|
||||||
|
const newLogs = logs.slice(lastLogCount)
|
||||||
|
lastLogCount = logs.length
|
||||||
|
|
||||||
|
for (const line of newLogs) {
|
||||||
|
send(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendNewLogs()
|
||||||
|
const unsub = onChange(sendNewLogs)
|
||||||
|
return () => unsub()
|
||||||
|
})
|
||||||
|
|
||||||
app.post('/api/apps/:app/start', c => {
|
app.post('/api/apps/:app/start', c => {
|
||||||
const appName = c.req.param('app')
|
const appName = c.req.param('app')
|
||||||
if (!appName) return c.json({ error: 'App not found' }, 404)
|
if (!appName) return c.json({ error: 'App not found' }, 404)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user