모니터링/Tempo
[Grafana faro] faro sdk
김붕어87
2025. 6. 25. 14:07
반응형
faro SDK는 웹 어플리에키션 성능 모니터링 자바스크립트 라이브러리입니다.
faro SDK 역할
1. RUM (Real User Monitoring)
Faro SDK는 웹사이트를 사용하는 실제 사용자들의 브라우저에서 발생하는 다양한 이벤트(페이지 로드 시간, 자바스크립트 에러, 사용자 인터랙션 등)를 수집합니다.
2. 성능 및 오류 데이터 수집
페이지 랜더링 속도, API 호출 지연, 자바스크립트 예외 같은 성능 지표와 오류 정보를 자동으로 수집해줍니다.
3. Trace 및 분산 추적 지원
Faro SDK의 일부 모듈(@grafana/faro-web-tracing)은 OpenTelemetry 표준 기반의 트레이스 데이터를 생성해,
분산 시스템에서 서비스 간 호출 흐름을 추적할 수 있도록 합니다.
4. Grafana 통합
수집된 데이터는 Grafana의 Observability 도구와 연동하여 시각화 및 분석이 가능합니다.
Observability 도구 : Tempo, Loki, Prometehus, Alloy 등)
5. 간편한 설치와 설정
NPM 패키지로 제공되어 React, Vue, Angular 등 다양한 프레임워크에 쉽게 적용 가능
공식 메뉴얼 : https://grafana.com/oss/faro/
https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/
테스트 링크 : https://github.com/grafana/quickpizza?tab=readme-ov-file
faro sdk : https://classic.yarnpkg.com/en/package/@grafana/faro-web-sdk
grafana dashboard : https://grafana.com/grafana/dashboards/22784-lightweight-apm-for-opentelemetry/
- Grafana으로 정보 확인가능
데이터 흐름 : POD -> Faro SDK -> Otel -> Tempo -> Grafana
[ 폴더 구조 ]
Dockerfile
index.html
package.json
tsconfig.json
vite.config.ts
public/index.html
src/main.ts
Dockerfile
FROM node:18 as build
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Faro SDK Demo</title>
</head>
<body>
<h1>Hello Faro</h1>
<button onclick="throw new Error('Test Error')">Trigger Error</button>
<!-- 메인 TypeScript/JavaScript 파일 불러오기 -->
<script type="module" src="/src/main.ts"></script>
</body>
</html>
package.json
{
"name": "faro-demo",
"version": "1.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@grafana/faro-web-sdk": "^1.4.0",
"@grafana/faro-web-tracing": "^1.4.0"
},
"devDependencies": {
"typescript": "^5.0.0",
"vite": "^5.0.0"
}
}
tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"esModuleInterop": true,
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": true
},
"include": ["src"]
}
vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
root: './',
build: {
outDir: 'dist',
}
});
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Faro SDK Demo</title>
</head>
<body>
<h1>Hello Faro</h1>
<button onclick="throw new Error('Test Error')">Trigger Error</button>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
src/main.ts
import { initializeFaro, getWebInstrumentations } from '@grafana/faro-web-sdk';
import { TracingInstrumentation } from '@grafana/faro-web-tracing';
const faro = initializeFaro({
url: 'https://trace.xxx..com/v1/faro', // 수집기로 들어감
instrumentations: [
...getWebInstrumentations({ captureConsole: true }), // console.log, error 등 자동 캡처
new TracingInstrumentation(),
],
app: {
name: 'faro-demo',
version: '1.0.0',
},
});
// ✅ 수동으로 trace 시작 + 로그 전송
faro.api.getOTEL()?.trace.getTracer('faro-demo')
.startActiveSpan('manual-web-trace', (span) => {
faro.api.pushLog(['trace 시작됨']);
console.log('[Trace]', {
traceId: span.spanContext().traceId,
spanId: span.spanContext().spanId,
});
span.end();
});
// ✅ 자동 에러 캡처 예시
throw new Error('oh no!');
npm install
npm run build
도커 빌드
테스트 방법
# tempo 정보가 수집이 되었는지 확인
curl -G "http:// tempoIP :3100/api/search" \
--data-urlencode 'q=service.name="faro-demo"' \
--data-urlencode 'limit=10' \
--data-urlencode "start=$(($(date +%s)-3600))" \
--data-urlencode "end=$(date +%s)"
# tempo에 입력 테스트
curl -X POST "http:// tempoIP :3100/api/search" \ \
-H "Content-Type: application/json" \
-d '{
"query": "service.name = \"faro-demo\"",
"start": "'$(($(date +%s)*1000000000 - 3600000000000))'",
"end": "'$(($(date +%s)*1000000000))'",
"limit": 10
}'
curl -X POST "http:// tempoIP :3100/api/faro" -H "Content-Type: application/json" -d '{"meta":{"app":{"name":"test-app"}}, "events":[]}'
# Otel에 입력 테스트
curl -X POST http:// otel IP :4318/v1/traces \
-H "Content-Type: application/json" \
-d '{
"resourceSpans": [{
"resource": {
"attributes": [{
"key": "service.name",
"value": { "stringValue": "curl-trace-test" }
}]
},
"scopeSpans": [{
"spans": [{
"traceId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"spanId": "bbbbbbbbbbbbbbbb",
"name": "curl-test-span",
"kind": 1,
"startTimeUnixNano": "1690000000000000000",
"endTimeUnixNano": "1690000001000000000"
}]
}]
}]
}'
반응형