브라우저 Telemetry 프록시 및 코어 웹 바이탈
Telemetry JavaScript SDK는 비밀 API 키를 사용하며 신뢰할 수 있는 서버 코드에 속합니다. 해당 키를 브라우저 애플리케이션에 묶지 마십시오. 핵심 웹 바이탈 또는 제한된 프런트엔드 안정성 이벤트를 수집하려면 허용 목록에 있는 작은 페이로드를 동일한 원본 엔드포인트로 보내고 해당 엔드포인트가 이를 Telemetry로 전달하도록 합니다.
이 디자인은 자격 증명을 서버 측에 유지하고 애플리케이션에 동의, 원본 확인, 속도 제한, 필드 유형, 페이로드 크기 및 개인 정보 보호 규칙을 적용할 수 있는 한 장소를 제공합니다.
건축
browser measurement
-> POST /api/browser-telemetry
-> origin, size, rate, and schema checks
-> server-side telemetry-sh client
-> browser_performance_measured table
프록시는 일반 로그 엔드포인트가 아닙니다. 알려진 이벤트 이름과 알려진 필드만 허용합니다. 클라이언트가 제공한 테이블 이름이나 Telemetry API 키를 절대로 수락하지 마세요.
브라우저 계약 정의
핵심 웹 바이탈의 경우 지표당 하나의 이벤트를 쉽게 검증할 수 있습니다.
type BrowserMetric = {
event_name: "browser_performance_measured";
metric_name: "CLS" | "INP" | "LCP";
metric_value: number;
metric_id: string;
route_template: string;
release: string;
navigation_type: string;
};
location.href가 아닌 /projects/:id와 같은 경로 템플릿을 사용하십시오. 쿼리 문자열, DOM 텍스트, 양식 값, 쿠키, 인증 데이터, 식별자가 포함된 리퍼러 또는 임의 오류 메시지를 보내지 마세요. 임의 메트릭 ID는 재전송의 중복을 제거하는 데 도움이 될 수 있지만 사이트 간 사용자 식별자가 되어서는 안 됩니다.
브라우저에서 웹 바이탈 수집
web-vitals 패키지는 현재 코어 웹 바이탈을 보고합니다. 정책 및 관할권에 따라 동의가 필요한 경우 동의 후 전송:
import { onCLS, onINP, onLCP, type Metric } from "web-vitals";
function reportMetric(metric: Metric) {
const body = JSON.stringify({
event_name: "browser_performance_measured",
metric_name: metric.name,
metric_value: metric.value,
metric_id: metric.id,
route_template: routeTemplateFor(location.pathname),
release: window.__APP_RELEASE__,
navigation_type: metric.navigationType,
});
if (navigator.sendBeacon) {
navigator.sendBeacon(
"/api/browser-telemetry",
new Blob([body], { type: "application/json" }),
);
return;
}
void fetch("/api/browser-telemetry", {
method: "POST",
headers: { "content-type": "application/json" },
body,
keepalive: true,
credentials: "same-origin",
});
}
onCLS(reportMetric);
onINP(reportMetric);
onLCP(reportMetric);
sendBeacon는 페이지 종료 중 작은 최선의 페이로드에 적합합니다. 전송이 보장되지 않으며 브라우저 확장 프로그램이 요청을 차단할 수 있으며 사용자는 전송 전에 페이지를 닫을 수 있습니다. 브라우저 측정값을 정확한 청구 또는 감사 원장이 아닌 샘플링된 경험 데이터로 취급하십시오.
서버에서 검증 및 전달
엔드포인트는 알 수 없는 출처, 이벤트 이름, 지표 이름, 무한한 값, 너무 큰 본문 및 예상치 못한 필드를 거부해야 합니다. 아래 예는 경계를 보여줍니다. 요청 및 응답 기본 요소를 서버 프레임워크에 맞게 조정합니다.
import { Telemetry } from "telemetry-sh";
const telemetry = new Telemetry(process.env.TELEMETRY_API_KEY);
const allowedMetrics = new Set(["CLS", "INP", "LCP"]);
export async function POST(request: Request) {
if (!isAllowedSameOrigin(request)) {
return new Response("forbidden", { status: 403 });
}
const contentLength = Number(request.headers.get("content-length") || 0);
if (contentLength > 4096 || !(await rateLimit(request))) {
return new Response("rejected", { status: 429 });
}
const input = await request.json();
if (
input.event_name !== "browser_performance_measured" ||
!allowedMetrics.has(input.metric_name) ||
!Number.isFinite(input.metric_value) ||
!isAllowedRouteTemplate(input.route_template)
) {
return new Response("invalid event", { status: 400 });
}
await telemetry.log("browser_performance_measured", {
metric_name: input.metric_name,
metric_value: input.metric_value,
metric_id: boundedString(input.metric_id, 80),
route_template: input.route_template,
release: boundedString(input.release, 80),
navigation_type: boundedCategory(input.navigation_type),
});
return new Response(null, { status: 202 });
}
프로덕션에서는 서버 프로세스당 한 번씩 클라이언트를 초기화하고, 제한된 업스트림 제한 시간을 사용하고, 원격 분석 실패가 202, 204 또는 재시도 가능한 응답을 반환할지 여부를 결정합니다. 브라우저 재시도 루프를 피하세요. 네트워크 및 세션 경계에 따른 작은 속도 제한으로 남용을 줄일 수 있지만 이벤트에 원시 IP 주소를 저장하지 마십시오.
보안 및 개인정보 보호 체크리스트
- 서버 런타임에서만
TELEMETRY_API_KEY를 유지하십시오. - 엔드포인트를 동일한 출처 요청과 예상되는 메서드 및 콘텐츠 유형으로 제한하세요.
- JSON를 구문 분석하기 전에 작은 본문 제한을 적용합니다.
- 허용 목록 이벤트 이름, 필드, 카테고리, 경로 템플릿 및 숫자 범위.
- 업스트림 API를 호출하기 전 속도 제한.
- 교차 출처 수집이 의도적이고 검토된 제품이 아닌 한 허용적인 CORS를 사용하지 마십시오.
- 수집하기 전에 귀하의 동의 및 거부 규칙을 적용하십시오.
- 모든 식별자에 대한 보존 및 삭제 동작을 정의합니다.
- 거부된 페이로드를 복사하지 않고 거부되고 속도가 제한된 요청을 모니터링합니다.
엔드포인트가 자격 증명을 수락하거나 사용자 연결 상태를 변경하는 경우 CSRF 방어는 여전히 중요합니다. 익명의 동일 출처 측정 엔드포인트의 경우 출처 검증, 엄격한 콘텐츠 유형, 사용자별 페이로드가 적절한 경계가 될 수 있습니다. 애플리케이션의 보안 모델을 통해 해당 선택을 확인하십시오.
데이터 확인
먼저 비프로덕션 환경에 배포하세요. 다음 사항을 확인하세요.
- 브라우저 번들에는 Telemetry 키가 없습니다.
- 알 수 없는 이벤트 이름, 추가 필드, 원시 URL 및 크기가 너무 큰 본문은 거부됩니다.
- 유효한 CLS, INP 및 LCP 이벤트는 숫자 값과 함께 도착합니다.
- 차단되거나 실패한 수집 요청은 탐색에 영향을 주지 않습니다.
- 릴리스 및 경로 값은 그룹화할 수 있을 만큼 안정적입니다.
- 스파스 경로는 시끄러운 알림에 사용되지 않습니다.
경로 및 릴리스별 코어 웹 바이탈 레시피를 사용하여 측정치 외에 샘플 수를 유지합니다. SQL을 사용한 프런트엔드 안정성 모니터링, JavaScript SDK 가이드 및 민감한 데이터 수정을 계속 진행하세요.