zen: log ip prefix
This commit is contained in:
@@ -21,6 +21,7 @@ export default {
|
|||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
const ip = event.event.request.headers["x-real-ip"]
|
||||||
let data: Record<string, unknown> = {
|
let data: Record<string, unknown> = {
|
||||||
"cf.continent": event.event.request.cf?.continent,
|
"cf.continent": event.event.request.cf?.continent,
|
||||||
"cf.country": event.event.request.cf?.country,
|
"cf.country": event.event.request.cf?.country,
|
||||||
@@ -32,7 +33,8 @@ export default {
|
|||||||
duration: event.wallTime,
|
duration: event.wallTime,
|
||||||
request_length: parseInt(event.event.request.headers["content-length"] ?? "0"),
|
request_length: parseInt(event.event.request.headers["content-length"] ?? "0"),
|
||||||
status: event.event.response?.status ?? 0,
|
status: event.event.response?.status ?? 0,
|
||||||
ip: event.event.request.headers["x-real-ip"],
|
ip,
|
||||||
|
"ip.prefix": ipPrefix(ip),
|
||||||
}
|
}
|
||||||
const time = new Date(event.eventTimestamp ?? Date.now()).toISOString()
|
const time = new Date(event.eventTimestamp ?? Date.now()).toISOString()
|
||||||
const events = [
|
const events = [
|
||||||
@@ -110,6 +112,7 @@ function toLakeEvent(time: string, data: Record<string, unknown>) {
|
|||||||
request_length: integer(data, "request_length"),
|
request_length: integer(data, "request_length"),
|
||||||
status: integer(data, "status"),
|
status: integer(data, "status"),
|
||||||
ip: string(data, "ip"),
|
ip: string(data, "ip"),
|
||||||
|
ip_prefix: string(data, "ip.prefix"),
|
||||||
is_stream: boolean(data, "is_stream"),
|
is_stream: boolean(data, "is_stream"),
|
||||||
session: string(data, "session"),
|
session: string(data, "session"),
|
||||||
request: string(data, "request"),
|
request: string(data, "request"),
|
||||||
@@ -146,15 +149,32 @@ function toLakeEvent(time: string, data: Record<string, unknown>) {
|
|||||||
cost_cache_read_microcents: integer(data, "cost.cache_read.microcents"),
|
cost_cache_read_microcents: integer(data, "cost.cache_read.microcents"),
|
||||||
cost_cache_write_microcents: integer(data, "cost.cache_write.microcents"),
|
cost_cache_write_microcents: integer(data, "cost.cache_write.microcents"),
|
||||||
cost_total_microcents: integer(data, "cost.total.microcents"),
|
cost_total_microcents: integer(data, "cost.total.microcents"),
|
||||||
cost_input: integer(data, "cost.input"),
|
|
||||||
cost_output: integer(data, "cost.output"),
|
|
||||||
cost_cache_read: integer(data, "cost.cache_read"),
|
|
||||||
cost_cache_write_5m: integer(data, "cost.cache_write_5m"),
|
|
||||||
cost_cache_write_1h: integer(data, "cost.cache_write_1h"),
|
|
||||||
cost_total: integer(data, "cost.total"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a stable lookup key for an IP address.
|
||||||
|
// IPv4: full address as /32 (e.g. "203.0.113.45/32").
|
||||||
|
// IPv6: the /64 network prefix (e.g. "2001:db8:abcd:1234::/64"). ISPs commonly
|
||||||
|
// rotate the lower 64 host bits via SLAAC privacy extensions (RFC 8981), so
|
||||||
|
// grouping by /64 collapses those rotations into one key.
|
||||||
|
function ipPrefix(ip: string | undefined) {
|
||||||
|
if (!ip) return undefined
|
||||||
|
if (ip.includes(".") && !ip.includes(":")) return `${ip}/32`
|
||||||
|
if (!ip.includes(":")) return undefined
|
||||||
|
|
||||||
|
// Expand "::" to its full form, then keep the first 4 hextets.
|
||||||
|
const [head, tail] = ip.split("::") as [string, string | undefined]
|
||||||
|
const headParts = head ? head.split(":") : []
|
||||||
|
const tailParts = tail !== undefined ? tail.split(":") : []
|
||||||
|
const missing = 8 - headParts.length - tailParts.length
|
||||||
|
if (missing < 0) return undefined
|
||||||
|
const full = [...headParts, ...new Array(missing).fill("0"), ...tailParts]
|
||||||
|
if (full.length !== 8) return undefined
|
||||||
|
|
||||||
|
const prefix = full.slice(0, 4).map((part) => part.toLowerCase().replace(/^0+(?=.)/, "")).join(":")
|
||||||
|
return `${prefix}::/64`
|
||||||
|
}
|
||||||
|
|
||||||
function string(data: Record<string, unknown>, key: string) {
|
function string(data: Record<string, unknown>, key: string) {
|
||||||
const value = data[key]
|
const value = data[key]
|
||||||
if (typeof value === "string") return value
|
if (typeof value === "string") return value
|
||||||
|
|||||||
Reference in New Issue
Block a user