better otel i think
Build and Publish / Metadata (push) Successful in 2s
Build and Publish / BuildAndDeployAmd64 (push) Successful in 1m26s

This commit is contained in:
mats committed 2026-09-19 19:14:51 +02:00
1 parent 6edbdc340d
commit 8f670dfa2f
16 files changed
+1129 -675

No files matched your search

+21 -10
View File
@@ -106,8 +106,8 @@ interface RawFrontendRecord {
release?: string
environment?: string
path?: string
vitalName?: string
vitalValue?: number
/** Metric values from a `page_vitals` beacon record (one per page view snapshot). */
vitals?: Record<string, number>
isError: boolean
isHttpFailure: boolean
exceptionType?: string
@@ -121,6 +121,20 @@ interface RawFrontendRecord {
breadcrumbs: ParsedBreadcrumb[]
}
/** Reads `{metrics: {LCP: {value}}}` from a page_vitals record body into name → value. */
function parseVitals(body?: string): Record<string, number> {
const out: Record<string, number> = {}
try {
const metrics = (JSON.parse(body ?? "") as { metrics?: Record<string, { value?: number }> }).metrics ?? {}
for (const [name, m] of Object.entries(metrics)) {
if (typeof m?.value === "number") out[name.toUpperCase()] = m.value
}
} catch {
/* not a vitals body */
}
return out
}
function extractFrontendRecords(logs: LogEntry[]): RawFrontendRecord[] {
const out: RawFrontendRecord[] = []
@@ -134,13 +148,13 @@ function extractFrontendRecords(logs: LogEntry[]): RawFrontendRecord[] {
;(sl.logRecords ?? []).forEach((r) => {
const attrs = r.attributes ?? []
const source = getAttributeValue(attrs, "source")
const vitalName = getAttributeValue(attrs, "rum.vital")
const isVitals = getAttributeValue(attrs, "rum.event") === "page_vitals"
const browserUrl = getAttributeValue(attrs, "browser.url")
const sessionId = getAttributeValue(attrs, "session.id")
const isRumScope = scopeName === "otel-rum"
const isFrontend =
source === "frontend" || isRumScope || Boolean(vitalName) || Boolean(browserUrl) || Boolean(sessionId)
source === "frontend" || isRumScope || isVitals || Boolean(browserUrl) || Boolean(sessionId)
if (!isFrontend) return
let path: string | undefined
@@ -157,7 +171,6 @@ function extractFrontendRecords(logs: LogEntry[]): RawFrontendRecord[] {
const sevNum = r.severityNumber ?? 0
const isErr = (sevNum >= 17 || excType !== "") && !isHttp
const vitalValStr = getAttributeValue(attrs, "rum.value")
const httpStatusStr = getAttributeValue(attrs, "http.response.status_code")
out.push({
@@ -168,8 +181,7 @@ function extractFrontendRecords(logs: LogEntry[]): RawFrontendRecord[] {
release: getAttributeValue(attrs, "service.release") || undefined,
environment: getAttributeValue(attrs, "service.environment") || undefined,
path,
vitalName: vitalName || undefined,
vitalValue: vitalValStr ? parseFloat(vitalValStr) : undefined,
vitals: isVitals ? parseVitals(r.body?.stringValue) : undefined,
isError: isErr,
isHttpFailure: isHttp,
exceptionType: excType || undefined,
@@ -227,9 +239,8 @@ export function buildRumSessions(logs: LogEntry[]): RumSession[] {
seenUrls.add(r.path)
urls.push(r.path)
}
if (r.vitalName && r.vitalValue !== undefined) {
vitals[r.vitalName.toUpperCase()] = r.vitalValue
}
// Each beacon is a full snapshot of one page view; later snapshots win.
if (r.vitals) Object.assign(vitals, r.vitals)
if (r.isError) {
errorCount += 1
errors.push({