feat: add latitude/longitude to access logs

Extends access logging system to support geographic coordinates:
- Adds `doublesMap` for latitude/longitude data
- Updates type definitions to handle numeric values
- Implements conversion functions for double values
- Captures coordinates from Cloudflare headers

Enhances analytics capabilities for real-time globe visualization
This commit is contained in:
ccbikai 2025-05-11 18:33:47 +08:00
parent 189c52dd4d
commit dc23ff02a2

View file

@ -36,27 +36,59 @@ export const blobsMap = {
blob15: 'deviceType',
} as const
export const doublesMap = {
double1: 'latitude',
double2: 'longitude',
} as const
export type BlobsMap = typeof blobsMap
export type BlobsKey = keyof BlobsMap
export type LogsKey = BlobsMap[BlobsKey]
export type LogsMap = { [key in LogsKey]: string | undefined }
export const logsMap: LogsMap = Object.entries(blobsMap).reduce((acc, [k, v]) => ({ ...acc, [v]: k }), {}) as LogsMap
export type DoublesMap = typeof doublesMap
export type DoublesKey = keyof DoublesMap
export type LogsKey = BlobsMap[BlobsKey] | DoublesMap[DoublesKey]
export type LogsMap = {
[key in BlobsMap[BlobsKey]]: string | undefined
} & {
[key in DoublesMap[DoublesKey]]?: number | undefined
}
export const logsMap = {
...Object.entries(blobsMap).reduce((acc, [k, v]) => ({ ...acc, [v]: k }), {}),
...Object.entries(doublesMap).reduce((acc, [k, v]) => ({ ...acc, [v]: k }), {}),
} as LogsMap
function logs2blobs(logs: LogsMap) {
// @ts-expect-error todo
return Object.keys(blobsMap).sort((a, b) => toBlobNumber(a) - toBlobNumber(b)).map(key => logs[blobsMap[key]] || '')
return (Object.keys(blobsMap) as BlobsKey[])
.sort((a, b) => toBlobNumber(a) - toBlobNumber(b))
.map(key => String(logs[blobsMap[key] as LogsKey] || ''))
}
function blobs2logs(blobs: string[]) {
const logsList = Object.keys(blobsMap)
// @ts-expect-error todo
return blobs.reduce((logs: LogsMap, blob, i) => {
// @ts-expect-error todo
logs[blobsMap[logsList[i]]] = blob
return blobs.reduce((logs, blob, i) => {
const key = blobsMap[logsList[i] as BlobsKey]
logs[key] = blob
return logs
}, {})
}, {} as Partial<LogsMap>)
}
function logs2doubles(logs: LogsMap) {
return (Object.keys(doublesMap) as DoublesKey[])
.sort((a, b) => toBlobNumber(a) - toBlobNumber(b))
.map(key => Number(logs[doublesMap[key] as LogsKey] || 0))
}
function doubles2logs(doubles: number[]) {
const logsList = Object.keys(doublesMap)
return doubles.reduce((logs, double, i) => {
const key = doublesMap[logsList[i] as DoublesKey]
logs[key] = double
return logs
}, {} as Partial<LogsMap>)
}
export function useAccessLog(event: H3Event) {
@ -108,16 +140,21 @@ export function useAccessLog(event: H3Event) {
browserType: uaInfo?.browser?.type,
device: uaInfo?.device?.model,
deviceType: uaInfo?.device?.type,
// For RealTime Globe
latitude: Number(cf?.latitude || getHeader(event, 'cf-iplatitude') || 0),
longitude: Number(cf?.longitude || getHeader(event, 'cf-iplongitude') || 0),
}
if (process.env.NODE_ENV === 'production') {
return hubAnalytics().put({
indexes: [link.id], // only one index
blobs: logs2blobs(accessLogs),
doubles: logs2doubles(accessLogs),
})
}
else {
console.log('access logs:', logs2blobs(accessLogs), blobs2logs(logs2blobs(accessLogs)))
console.log('access logs:', accessLogs, logs2blobs(accessLogs), logs2doubles(accessLogs), { ...blobs2logs(logs2blobs(accessLogs)), ...doubles2logs(logs2doubles(accessLogs)) })
return Promise.resolve()
}
}