fix: (regression beta) admin/logs: not showing country and notes for past lines
Massimo Melina committed
Feb 12, 2024 at 16:24 UTC
c4dc87e3ec697677620d4e29db067e2cd216a644
3 files changed
+28
-19
admin/src/LogsPage.ts
+18
-18
@@ -5,7 +5,7 @@ import { Box, Tab, Tabs } from '@mui/material'
5
import { API_URL, useApi, useApiList } from './api'
6
import { DataTable } from './DataTable'
7
import { CFG, Dict, formatBytes, HTTP_UNAUTHORIZED, newDialog, prefix, shortenAgent, splitAt, tryJson,
8
- typedKeys, NBSP, _dbg } from '@hfs/shared'
8
+ typedKeys, NBSP, _dbg, mapFilter } from '@hfs/shared'
9
import { logLabels } from './OptionsPage'
10
import {
11
NetmaskField, Flex, IconBtn, useBreakpoint, usePauseButton, useToggleButton, WildcardsSupported, Country,
@@ -94,6 +94,7 @@ function LogFile({ file, addToFooter, hidden }: { hidden?: boolean, file: string
94
const [limited, setLimited] = useState(true)
95
const [skipped, setSkipped] = useState(0)
96
const MAX = 2**20
97
+ const invert = true
98
useApi('get_log_file', { file, range: limited || !skipped ? -MAX : `0-${skipped}` }, {
99
skipParse: true, skipLog: true,
100
onResponse(res, body) {
@@ -111,26 +112,11 @@ function LogFile({ file, addToFooter, hidden }: { hidden?: boolean, file: string
112
toast(`Entire log loaded, ${formatBytes(skipped)}`)
113
setSkipped(0)
114
}
114
- const treated = lines.map(parseLogLine).filter(Boolean).reverse()
115
+ const treated = mapFilter(lines, (x: any, i) => enhanceLogLine(parseLogLine(x, i)), Boolean, invert)
116
setList(x => [...x, ...treated])
117
}
118
})
118
- const { list, setList, error, connecting } = useApiList('get_log', { file }, {
119
- invert: true,
120
- pause,
121
- map(x) {
122
- const { extra } = x
123
- if (extra?.country && !showCountry)
124
- setShowCountry(true)
125
- if (extra?.ua && !showAgent)
126
- setShowAgent(true)
127
- x.notes = extra?.dl ? "fully downloaded"
128
- : (x.method === 'PUT' || extra?.ul) ? "uploaded " + formatBytes(extra.size, { sep: NBSP })
129
- : x.status === HTTP_UNAUTHORIZED && x.uri?.startsWith(API_URL + 'loginSrp') ? "login failed" + prefix(':\n', extra?.u)
130
- : x.notes
131
- return x
132
- }
133
- })
119
+ const { list, setList, error, connecting } = useApiList('get_log', { file }, { invert, pause, map: enhanceLogLine })
120
const tsColumn: GridColDef = {
121
field: 'ts',
122
headerName: "Timestamp",
@@ -262,6 +248,20 @@ function LogFile({ file, addToFooter, hidden }: { hidden?: boolean, file: string
248
},
249
]
250
})
251
+
252
+ function enhanceLogLine(x: any) {
253
+ if (!x) return
254
+ const { extra } = x
255
+ if (extra?.country && !showCountry)
256
+ setShowCountry(true)
257
+ if (extra?.ua && !showAgent)
258
+ setShowAgent(true)
259
+ x.notes = extra?.dl ? "fully downloaded"
260
+ : (x.method === 'PUT' || extra?.ul) ? "uploaded " + formatBytes(extra.size, { sep: NBSP })
261
+ : x.status === HTTP_UNAUTHORIZED && x.uri?.startsWith(API_URL + 'loginSrp') ? "login failed" + prefix(':\n', extra?.u)
262
+ : x.notes
263
+ return x
264
+ }
265
}
266
267
export function agentIcons(agent: string) {
src/cross.ts
+9
@@ -440,6 +440,15 @@ export function inCommon<T extends string | unknown[]>(a: T, b: T) {
440
return i
441
}
442
443
+export function mapFilter<T=unknown, R=T>(arr: T[], map: (x:T, idx: number) => R, filter=(x: R) => x === undefined, invert=false) {
444
+ return arr[invert ? 'reduceRight' : 'reduce']((ret, x, idx) => {
445
+ const y = map(x, idx)
446
+ if (filter(y))
447
+ ret.push(y) // push is much faster than unshift, therefore invert using reduceRight https://measurethat.net/Benchmarks/Show/29/0/array-push-vs-unshift
448
+ return ret
449
+ }, [] as R[])
450
+}
451
+
452
export function shortenAgent(agent: string) {
453
return _.findKey(BROWSERS, re => re.test(agent))
454
|| /^[^/(]+ ?/.exec(agent)?.[0]
src/log.ts
+1
-1
@@ -130,7 +130,7 @@ export const logMw: Koa.Middleware = async (ctx, next) => {
130
ctx.req.httpVersion,
131
ctx.status,
132
length?.toString() ?? '-',
133
- _.isEmpty(extra) ? '' : JSON.stringify(JSON.stringify(extra)),
133
+ _.isEmpty(extra) ? '' : JSON.stringify(JSON.stringify(extra)), // jsonize twice, as we need a field enclosed by double-quotes
134
))
135
})
136
}