فهرست منبع

zen: log ip prefix

Frank 2 ماه پیش
والد
کامیت
51a9b0baad
1فایلهای تغییر یافته به همراه27 افزوده شده و 7 حذف شده
  1. 27 7
      packages/console/function/src/log-processor.ts

+ 27 - 7
packages/console/function/src/log-processor.ts

@@ -21,6 +21,7 @@ export default {
       )
         continue
 
+      const ip = event.event.request.headers["x-real-ip"]
       let data: Record<string, unknown> = {
         "cf.continent": event.event.request.cf?.continent,
         "cf.country": event.event.request.cf?.country,
@@ -32,7 +33,8 @@ export default {
         duration: event.wallTime,
         request_length: parseInt(event.event.request.headers["content-length"] ?? "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 events = [
@@ -110,6 +112,7 @@ function toLakeEvent(time: string, data: Record<string, unknown>) {
     request_length: integer(data, "request_length"),
     status: integer(data, "status"),
     ip: string(data, "ip"),
+    ip_prefix: string(data, "ip.prefix"),
     is_stream: boolean(data, "is_stream"),
     session: string(data, "session"),
     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_write_microcents: integer(data, "cost.cache_write.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) {
   const value = data[key]
   if (typeof value === "string") return value