include db for gitea build
This commit is contained in:
1 parent
8de4a2e010
commit
645f923175
33 files changed
+1490
-150
No files matched your search
@@ -0,0 +1,67 @@
|
||||
// Resolves the real client of a trace. One request is recorded by several
|
||||
// spans (ingress outer span, ingress inner span on a loopback hop, the app
|
||||
// span) and only the outer one sees the public peer, so a single span's
|
||||
// net.peer.ip is often 127.0.0.1 or a pod address. The Go side does the same
|
||||
// walk in internal/tracectx; keep the two definitions of "public" in step.
|
||||
import type { ProcessedSpan, ProcessedTrace } from "../components/TraceVisualization"
|
||||
|
||||
const PEER_KEYS = ["net.peer.ip", "client.address", "network.peer.address", "net.sock.peer.addr"]
|
||||
|
||||
const inRange = (a: number, b: number, lo: number, hi: number) => a === lo && b >= 0 && b <= hi
|
||||
|
||||
/** True for addresses that could be a real remote client: not loopback, private, link-local, CGNAT or reserved. */
|
||||
export const isPublicIp = (ip: string): boolean => {
|
||||
const v = ip.trim().toLowerCase()
|
||||
if (!v) return false
|
||||
if (v.includes(":")) {
|
||||
return !(v === "::1" || v === "::" || v.startsWith("fe80:") || v.startsWith("fc") || v.startsWith("fd") || v.startsWith("ff") || v.startsWith("::ffff:"))
|
||||
}
|
||||
const parts = v.split(".").map(Number)
|
||||
if (parts.length !== 4 || parts.some((n) => !Number.isInteger(n) || n < 0 || n > 255)) return false
|
||||
const [a, b] = parts
|
||||
if (a === 0 || a === 10 || a === 127 || a >= 224) return false
|
||||
if (a === 169 && b === 254) return false
|
||||
if (inRange(a, b, 172, 31) && b >= 16) return false
|
||||
if (a === 192 && b === 168) return false
|
||||
if (a === 100 && b >= 64 && b <= 127) return false // CGNAT / Tailscale
|
||||
if (a === 198 && (b === 18 || b === 19)) return false
|
||||
return true
|
||||
}
|
||||
|
||||
export interface TraceClient {
|
||||
ip: string
|
||||
service: string
|
||||
spanId: string
|
||||
/** Ancestors between the outermost span and the span that carried the address (0 = outermost). */
|
||||
depth: number
|
||||
/** True when at least one span in the trace saw only an internal hop (loopback / pod / NAT). */
|
||||
hadInternalHops: boolean
|
||||
}
|
||||
|
||||
/** The public peer address seen closest to the outside of the trace, or null when every hop is internal. */
|
||||
export const resolveTraceClient = (trace: ProcessedTrace): TraceClient | null => {
|
||||
const byId = new Map<string, ProcessedSpan>(trace.spans.map((s) => [s.spanId, s]))
|
||||
const depthOf = (span: ProcessedSpan): number => {
|
||||
let depth = 0
|
||||
let cur: ProcessedSpan | undefined = span
|
||||
while (cur?.parentSpanId && depth < 32) {
|
||||
cur = byId.get(cur.parentSpanId)
|
||||
if (!cur) break
|
||||
depth++
|
||||
}
|
||||
return depth
|
||||
}
|
||||
let best: TraceClient | null = null
|
||||
let internal = false
|
||||
for (const span of trace.spans) {
|
||||
const ip = PEER_KEYS.map((k) => span.formattedAttributes[k]).find(Boolean)
|
||||
if (!ip) continue
|
||||
if (!isPublicIp(ip)) {
|
||||
internal = true
|
||||
continue
|
||||
}
|
||||
const depth = depthOf(span)
|
||||
if (!best || depth < best.depth) best = { ip, service: span.service, spanId: span.spanId, depth, hadInternalHops: false }
|
||||
}
|
||||
return best ? { ...best, hadInternalHops: internal } : null
|
||||
}
|
||||
@@ -17,3 +17,6 @@ export const UA_CLASSES: { value: string; label: string }[] = [
|
||||
|
||||
export const uaClassLabel = (value?: string): string =>
|
||||
UA_CLASSES.find((c) => c.value === value)?.label ?? value ?? ""
|
||||
|
||||
/** Classes the "Hide crawlers" toggle hides: self-declared crawlers, agents and scanners, not monitors or HTTP libraries. */
|
||||
export const CRAWLER_CLASSES = ["ai_crawler", "ai_agent", "search_crawler", "seo_crawler", "scan_tool", "other_bot"]
|
||||
Reference in new issue
Block a user