React Native 애플리케이션에 OpenTelemetry 분산 추적을 통합하는 레퍼런스 구현체입니다. fetch 자동 계측과 수동 span/error 기록을 포함합니다.
OpenTelemetry는 Node.js와 브라우저 환경에서는 훌륭한 지원을 제공하지만, React Native 통합은 문서화되어 있지 않고 번들러 문제로 가득합니다. Metro 번들러는 package.json의 "exports" 필드를 지원하지 않고, 내부 상대 경로 import를 Node.js와 동일하게 해석하지 않아 OpenTelemetry 패키지를 import할 때 알 수 없는 "Module not found" 에러가 발생합니다.
이 저장소는 Metro 번들러 문제에 대한 실제 동작하는 해결책을 제공하여, 디버깅 없이 바로 앱 계측에 집중할 수 있도록 합니다. 수동 span, 에러 기록, fetch 자동 계측, OTLP export 등 필요한 텔레메트리 API 패턴도 함께 보여줍니다.
- 수동 span 생성 - 커스텀 속성을 가진 span을 생성하고 종료
- 에러 기록 - 예외를 span 이벤트로 캡처하고 에러 상태를 설정
- fetch 자동 계측 - 모든
fetch()호출이 HTTP 메서드, 상태 코드, URL과 함께 자동으로 추적 - 스코프 span - 비동기 작업을 위한
withSpan()헬퍼로 자동 에러 처리 - OTLP export - OTLP 호환 백엔드로 트레이스 전송 (Jaeger, Grafana Tempo, HyperDX 등)
┌─────────────────────┐ ┌──────────────────────┐ ┌─────────────────┐
│ React Native App │───▶│ Telemetry Manager │───▶│ OTLP Backend │
│ (src/App.tsx) │ │ (src/telemetry.ts) │ │ (Jaeger 등) │
│ │ │ │ │ │
│ - 수동 span │ │ - WebTracerProvider │ │ │
│ - fetch() 호출 │ │ - FetchInstr. │ │ │
│ │ │ - BatchSpanProcessor│ │ │
└─────────────────────┘ │ - OTLPTraceExporter │ └─────────────────┘
└──────────────────────┘
OTLP 호환 백엔드라면 모두 사용할 수 있습니다.
| 백엔드 | 엔드포인트 예시 | 인증 헤더 |
|---|---|---|
| Jaeger | http://localhost:4318/v1/traces |
(없음) |
| Grafana Tempo | https://<instance>.grafana.net/otlp/v1/traces |
Basic <base64> |
| HyperDX | https://in-otel.hyperdx.io/v1/traces |
<api-key> |
| Honeycomb | https://api.honeycomb.io/v1/traces |
<api-key> |
| Datadog | OTLP ingest 엔드포인트 | <api-key> |
| SigNoz | https://<instance>.signoz.io/v1/traces |
<api-key> |
- Node.js >= 18
- pnpm
- React Native 개발 환경 (설정 가이드)
- OTLP 호환 백엔드 (또는 로컬 Jaeger)
docker run -d --name jaeger \
-p 16686:16686 \
-p 4318:4318 \
jaegertracing/all-in-one:latesthttp://localhost:16686에서 Jaeger UI를 열어 트레이스를 확인할 수 있습니다.
git clone https://github.com/devlasbe/react-native-otel-example.git
cd react-native-otel-example
pnpm install
# OTLP 엔드포인트 설정
cp .env.example .env
# .env 파일에 백엔드 정보를 입력iOS:
cd ios && bundle install && bundle exec pod install && cd ..
pnpm iosAndroid:
pnpm android모든 설정은 .env 파일의 환경변수로 관리합니다:
| 변수 | 설명 | 기본값 |
|---|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT |
OTLP 트레이스 수집기 URL | http://localhost:4318/v1/traces |
OTEL_EXPORTER_OTLP_AUTH_HEADER |
인증 헤더 값 | (비어있음) |
OTEL_SERVICE_NAME |
트레이스에 표시되는 서비스 이름 | react-native-otel-example |
OTEL_SERVICE_VERSION |
트레이스에 표시되는 서비스 버전 | 1.0.0 |
코드에서 직접 설정할 수도 있습니다:
import telemetry from './src/telemetry';
telemetry.initialize({
endpoint: 'https://your-backend.com/v1/traces',
authHeader: 'Bearer your-token',
serviceName: 'my-app',
serviceVersion: '2.0.0',
});pnpm add @opentelemetry/sdk-trace-web \
@opentelemetry/sdk-trace-base \
@opentelemetry/exporter-trace-otlp-http \
@opentelemetry/resources \
@opentelemetry/instrumentation \
@opentelemetry/instrumentation-fetch \
@opentelemetry/api \
@opentelemetry/otlp-exporter-base \
@opentelemetry/semantic-conventionsmetro.config.js의 resolver 설정을 프로젝트의 Metro 설정에 추가합니다. 이 설정 없이는 OpenTelemetry 패키지의 모듈 해석이 실패합니다.
src/telemetry.ts를 프로젝트에 복사하고 설정을 조정합니다.
// 앱 진입점에서 초기화
import telemetry from './telemetry';
telemetry.initialize();
// span 생성
telemetry.createSpan('button-tap', { 'button.id': 'checkout' });
// 에러 기록
telemetry.recordError(new Error('Payment failed'));
// 비동기 작업을 위한 스코프 span
const result = await telemetry.withSpan('api-call', async (span) => {
span.setAttributes({ 'api.endpoint': '/orders' });
const response = await fetch('https://api.example.com/orders');
return response.json();
});
// fetch() 호출은 자동으로 계측됩니다 - 추가 코드 불필요이 저장소에서 가장 가치 있는 부분입니다. OpenTelemetry 패키지는 Node.js/브라우저 환경용으로 설계되어 Metro 번들러의 두 가지 제한사항에 부딪힙니다.
증상: Module not found: @opentelemetry/otlp-exporter-base/browser-http
원인: 패키지가 package.json의 "exports" 필드를 사용하여 하위 경로 import를 노출합니다. Metro의 기본 resolver는 "exports" 필드를 지원하지 않습니다.
해결: 해당 import에 대해서만 선택적으로 unstable_enablePackageExports를 활성화합니다:
resolveRequest: (context, moduleImport, platform) => {
if (moduleImport === '@opentelemetry/otlp-exporter-base/browser-http') {
return context.resolveRequest(
{ ...context, unstable_enablePackageExports: true },
moduleImport,
platform,
);
}
return context.resolveRequest(context, moduleImport, platform);
},증상: Module not found: ./semconvStability (@opentelemetry/instrumentation 내부)
원인: 패키지가 내부적으로 ./semconvStability를 상대 경로로 import합니다. Metro는 패키지의 컴파일된 출력 디렉토리 내부에서 발생하는 상대 경로를 Node.js와 동일하게 해석하지 못하여 모듈 해석에 실패합니다.
해결: Metro의 alias 기능을 사용하여 상대 경로를 절대 파일 경로로 매핑합니다:
alias: {
'./semconvStability': require.resolve(
'@opentelemetry/instrumentation/build/src/semconvStability.js',
),
},- React Native 0.80.2
- OpenTelemetry JS SDK 2.x
- TypeScript
- pnpm
- React Native 전용 tracer provider가 없어
@opentelemetry/sdk-trace-web의WebTracerProvider를 사용합니다 FetchInstrumentation은 전역fetch를 패치하므로, 다른 fetch 패칭 라이브러리와 충돌할 수 있습니다- React Navigation 연동 (화면별 span)은 포함되어 있지 않습니다
- 프로덕션 환경에서의 추적 성능 오버헤드는 사용 사례에 맞게 평가해야 합니다
MIT