RUM 구성¶
RUM 초기화 구성¶
| 필드 | 유형 | 필수 | 설명 |
|---|---|---|---|
| androidAppId | String | Android 필수 | Android 플랫폼의 app_id, 실제 사용자 모니터링(RUM) 콘솔에서 발급받음; Android 런타임에서만 읽음 |
| iOSAppId | String | iOS 필수 | iOS 플랫폼의 app_id, 실제 사용자 모니터링(RUM) 콘솔에서 발급받음; iOS 런타임에서만 읽음 |
| sampleRate | double | 아니요 | 샘플링 비율, 범위 [0,1], 0은 수집 안 함, 1은 전체 수집, 기본값 1. 동일한 session_id 내의 모든 View, Action, LongTask, Error 데이터에 적용 |
| sessionOnErrorSampleRate | double | 아니요 | 오류 수집 비율. sampleRate에 의해 샘플링되지 않은 세션에서 오류가 발생한 경우, 오류 발생 전 1분 범위의 데이터를 수집할 수 있음, 범위 [0,1], 기본값 0 |
| enableUserResource | bool | 아니요 | Flutter http Resource 자동 캡처 활성화 여부, 기본값 false. HttpOverrides.global을 수정하여 구현, 프로젝트에 맞춤 요구사항이 있는 경우 FTHttpOverrides를 상속해야 함 |
| enableNativeUserAction | bool | 아니요 | 네이티브 측 Action 자동 추적 여부. Android/iOS 네이티브 컨트롤 클릭 및 애플리케이션 시작 이벤트 포함, 기본값 false. Android는 ft-plugin 구성 필요, 시작 이벤트 수집은 Application 커스터마이징 필요 |
| enableNativeUserView | bool | 아니요 | 네이티브 페이지 자동 수집 여부, Android는 Activity 수집, iOS는 UIViewController 수집, 기본값 false |
| enableNativeSwiftUIUserView | bool | 아니요 | iOS: 네이티브 SwiftUI View 자동 추적 활성화 여부. enableNativeUserView를 함께 활성화해야 함 |
| enableNativeUserViewInFragment | bool | 아니요 | Android Fragment 페이지 자동 수집 여부, ft-plugin 구성 필요, 기본값 false, Android만 지원 |
| enableNativeUserResource | bool | 아니요 | 네이티브 네트워크 Resource 자동 수집 활성화 여부, Android는 OkHttp 요청 자동 수집, iOS는 네이티브 네트워크 요청 자동 수집, 기본값 false. 이 매개변수는 Flutter HttpClient 요청을 수집하는 enableUserResource와 별개의 독립적인 기능 |
| enableNativeAppUIBlock | bool | 아니요 | 네이티브 메인 스레드 지연(UI Block/Freeze) 자동 감지 활성화 여부, 기본값 false |
| nativeUiBlockDurationMS | int | 아니요 | 네이티브 메인 스레드 지연 감지 임계값, 단위 밀리초, enableNativeAppUIBlock 활성화 시에만 적용, 범위 [100, ). iOS 기본값 250ms, Android 기본값 1000ms |
| enableLongTask | bool | 아니요 | Flutter Dart 메인 Isolate 긴 작업 자동 감지 활성화 여부, 기본값 false |
| dartLongTaskThreshold | double | 아니요 | Flutter Dart 긴 작업 감지 임계값, 단위 초, 기본값 0.1 |
| enableTrackNativeAppANR | bool | 아니요 | 네이티브 ANR 모니터링 활성화 여부, 기본값 false. ANR은 애플리케이션이 지속적으로 응답하지 않는 상태를 감지하며, enableNativeAppUIBlock이 수집하는 단일 메인 스레드 지연과 다름; iOS는 메인 스레드 RunLoop를 통해 응답 없음 감지 |
| enableTrackNativeCrash | bool | 아니요 | 네이티브 크래시 모니터링 활성화 여부, 기본값 false. Android는 Java Crash 및 Native C/C++ Crash 수집; iOS는 Crash 수집, iosCrashMonitoringType을 통해 모니터링 유형 구성 가능 |
| errorMonitorType | int | 아니요 | RUM Error 데이터에 첨부할 보조 모니터링 정보 설정, ErrorMonitorType.battery, memory, cpu, all 지원, 호출 시 해당 .value 전달(예: ErrorMonitorType.all.value), 기본값 비활성화 |
| deviceMetricsMonitorType | int | 아니요 | RUM View 데이터에 첨부할 성능 모니터링 정보 설정, DeviceMetricsMonitorType.battery, memory, cpu, fps, all 지원, 호출 시 해당 .value 전달(예: DeviceMetricsMonitorType.all.value), 기본값 비활성화 |
| detectFrequency | enum DetectFrequency | 아니요 | View 성능 모니터링 샘플링 주기: DetectFrequency.normal은 500ms, frequent는 100ms, rare는 1000ms, 기본값 normal; deviceMetricsMonitorType 구성 시에만 의미 있음 |
| globalContext | Map | 아니요 | 사용자 정의 전역 매개변수. 추가 규칙은 충돌 필드 설명 참조 |
| rumCacheDiscard | enum | 아니요 | 폐기 전략: FTRUMCacheDiscard.discard 새 데이터 폐기(기본값), FTRUMCacheDiscard.discardOldest 오래된 데이터 폐기 |
| rumCacheLimitCount | int | 아니요 | 로컬 캐시 최대 RUM 항목 수 제한 [10_000, ), 기본값 100_000 |
| isInTakeUrl | bool Function(String url) | 아니요 | Flutter http Resource URL 필터 콜백. true 반환 시 필터링되어 수집 안 함, false 반환 시 수집. 사용 방법은 데이터 수집 사용자 정의 규칙 참조 |
| enableTraceWebView | bool | 아니요 | 네이티브 SDK를 통한 WebView 데이터 수집 활성화 여부, Android/iOS 지원, 기본값 true |
| allowWebViewHost | List |
아니요 | WebView 데이터 수집을 허용할 Host 목록 구성, enableTraceWebView와 함께 사용해야 함, Android/iOS 지원; 설정하지 않거나 null인 경우 모든 Host 수집 허용 |
| enableResourceHostIP | bool | 아니요 | 네이티브 Resource 요청의 Host IP 수집 여부, 기본값 false. enableNativeUserResource의 네이티브 네트워크 자동 수집에만 영향, enableUserResource가 수집하는 Flutter HttpClient Resource에는 적용되지 않음; iOS 13 이상 필요 |
| iosCrashMonitoringType | enum IOSCrashMonitoringType | 아니요 | iOS 크래시 모니터링 유형, iOS만 적용, enableTrackNativeCrash 활성화 필요. 옵션: machException, signal, cppException, nsException, system, applicationState, all, highCompatibility, 기본값 IOSCrashMonitoringType.highCompatibility |
RUM 사용자 데이터 추적¶
Action¶
사용 방법¶
/// action 추가
/// [actionName] action 이름
/// [actionType] action 유형
/// [property] 추가 속성 매개변수(선택 사항)
Future<void> startAction(String actionName, String actionType,
{Map<String, Object?>? property})
/// 고빈도 action 추가, 현재 Resource, LongTask, Error 이벤트와 연결하지 않음
Future<void> addAction(String actionName, String actionType,
{Map<String, Object?>? property})
코드 예제¶
FTRUMManager().startAction("action name", "action type");
FTRUMManager().addAction("action name", "action type");
View¶
자동 수집¶
MaterialApp.navigatorObservers에 FTRouteObserver를 추가하면 SDK가 Flutter 페이지 전환을 자동으로 수집할 수 있습니다. 페이지 이름(view_name)은 다음 방법으로 구성할 수 있습니다.
방법 1: routes를 통한 수집¶
MaterialApp.routes에 이동할 페이지를 설정합니다. routes의 key가 페이지 이름(view_name)이 됩니다.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeRoute(),
navigatorObservers: [
FTRouteObserver(),
],
routes: <String, WidgetBuilder>{
'logging': (BuildContext context) => Logging(),
'rum': (BuildContext context) => RUM(),
'tracing_custom': (BuildContext context) => CustomTracing(),
'tracing_auto': (BuildContext context) => AutoTracing(),
},
);
}
}
Navigator.pushNamed(context, "logging");
방법 2: FTMaterialPageRoute를 통한 수집¶
사용자 정의 FTMaterialPageRoute를 사용하여 위젯의 runtimeType에서 페이지 이름을 파싱합니다. 여기서 widget 클래스 이름이 페이지 이름(view_name)이 됩니다.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeRoute(),
navigatorObservers: [
FTRouteObserver(),
],
);
}
}
Navigator.of(context).push(
FTMaterialPageRoute(builder: (context) => new NoRouteNamePage()),
);
예제는 여기를 참조하세요.
방법 3: RouteSettings.name을 통한 수집¶
Route 유형 페이지에서 RouteSettings.name을 사용자 정의합니다. FTRouteObserver는 이 값을 우선적으로 가져옵니다. 이 방법은 Dialog 유형 페이지(예: showDialog(), showTimePicker() 등)에도 동일하게 적용됩니다.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeRoute(),
navigatorObservers: [
FTRouteObserver(),
],
);
}
}
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => new NoRouteNamePage(),
settings: RouteSettings(name: "RouteSettingName"),
),
);
위 세 가지 방법은 하나의 프로젝트에서 혼합하여 사용할 수 있습니다.
절전 모드 및 깨우기 이벤트 수집¶
0.5.1-pre.1 미만 버전에서 애플리케이션 절전 모드 및 깨우기 동작을 수집해야 하는 경우 다음 코드를 추가해야 합니다.
class _HomeState extends State<HomeRoute> {
@override
void initState() {
FTLifeRecycleHandler().initObserver();
}
@override
void dispose() {
FTLifeRecycleHandler().removeObserver();
}
}
자동 수집 필터 규칙은 데이터 수집 사용자 정의 규칙을 참조하세요.
사용자 정의 View¶
사용 방법¶
/// view 생성, 이 메서드는 [starView] 이전에 호출되어야 함
/// [viewName] 화면 이름
/// [duration] 페이지 로드 시간
Future<void> createView(String viewName, int duration)
/// view 시작
/// [viewName] 화면 이름
/// [viewReferer] 이전 화면 이름
/// [property] 추가 속성 매개변수(선택 사항)
Future<void> starView(String viewName, {Map<String, String>? property})
/// view 종료
/// [property] 추가 속성 매개변수(선택 사항)
Future<void> stopView({Map<String, String>? property})
코드 예제¶
FTRUMManager().createView("Current Page Name", 100000000);
FTRUMManager().starView("Current Page Name");
FTRUMManager().stopView();
자동 페이지 수집, 경로 필터링, 절전 모드/깨우기 리스닝 등 규칙은 데이터 수집 사용자 정의 규칙을 참조하세요.
Error¶
자동 수집¶
void main() async {
runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();
await FTMobileFlutter.sdkConfig(
datakitUrl: serverUrl,
debug: true,
);
await FTRUMManager().setConfig(
androidAppId: appAndroidId,
iOSAppId: appIOSId,
);
// Flutter 예외 캡처
FlutterError.onError = FTRUMManager().addFlutterError;
runApp(MyApp());
}, (Object error, StackTrace stack) {
// Error 데이터 추가
FTRUMManager().addError(error, stack);
});
}
사용자 정의 Error¶
사용 방법¶
/// 사용자 정의 오류 추가
/// [stack] 스택 로그
/// [message] 오류 메시지
/// [appState] 애플리케이션 상태
/// [errorType] 사용자 정의 errorType
/// [property] 추가 속성 매개변수(선택 사항)
Future<void> addCustomError(String stack, String message,
{Map<String, String>? property, String? errorType})
코드 예제¶
LongTask¶
자동 수집¶
FTRUMManager().setConfig에서 enableLongTask를 활성화하면 SDK가 Flutter Dart 메인 Isolate에서 임계값을 초과하는 블로킹 작업이 있는지 감지하고 LongTask 데이터를 생성합니다. 기본 임계값은 0.1초이며, dartLongTaskThreshold로 조정할 수 있습니다.
await FTRUMManager().setConfig(
androidAppId: appAndroidId,
iOSAppId: appIOSId,
enableLongTask: true,
dartLongTaskThreshold: 0.1,
);
사용자 정의 LongTask¶
사용 방법¶
/// LongTask 보고, duration 단위는 나노초
Future<void> addLongTask(String stack, int duration,
{Map<String, String>? property})
코드 예제¶
FTRUMManager().addLongTask(
"flutter_manual_long_task",
250000000,
property: {"long_task_source": "manual_report"},
);
자동 감지된 LongTask는 Dart 메인 Isolate 이벤트 루프 지연을 식별하는 데 사용되며, 수집되는 것은 블로킹 시간입니다. 블로킹을 유발한 비즈니스 코드 스택을 항상 얻을 수 있는 것은 아닙니다.
Resource¶
자동 수집¶
FTRUMManager().setConfig에서 enableUserResource를 활성화하여 구현합니다.
사용자 정의 Resource¶
사용 방법¶
/// 리소스 요청 시작
/// [key] 고유 id
/// [property] 추가 속성 매개변수(선택 사항)
Future<void> startResource(String key, {Map<String, String>? property})
/// 리소스 요청 종료
/// [key] 고유 id
/// [property] 추가 속성 매개변수(선택 사항)
Future<void> stopResource(String key, {Map<String, String>? property})
/// 리소스 데이터 메트릭 전송
Future<void> addResource({
required String key,
required String url,
required String httpMethod,
required Map<String, dynamic> requestHeader,
Map<String, dynamic>? responseHeader,
String? responseBody = "",
int? resourceStatus,
int? resourceSize,
String? resourceType,
FTRUMResourceMetrics? metrics,
})
| 필드 | 유형 | 설명 |
|---|---|---|
| resourceSize | int | 응답 본문 크기, 단위 byte |
| resourceType | String | 리소스 유형, 예: native, image, media, font, css, js |
| metrics.requestSize | num | 요청 크기, 요청 헤더 및 요청 본문 포함, 단위 byte |
| metrics.resourceHttpProtocol | String | Resource에서 사용하는 HTTP 프로토콜, 예: http/1.1 |
| metrics.reusedConnection | bool | 연결 재사용 여부 |
enableUserResource자동 수집을 활성화하면 SDK가 요청 메서드, 응답 헤더 및 연결 상태에 따라resourceType,requestSize,resourceHttpProtocol,reusedConnection등의 필드를 자동으로 추가합니다.
코드 예제¶
void httpClientGetHttp(String url) async {
var httpClient = HttpClient();
String key = Uuid().v4();
HttpClientResponse? response;
HttpClientRequest? request;
try {
request = await httpClient
.getUrl(Uri.parse(url))
.timeout(Duration(seconds: 10));
FTRUMManager().startResource(key);
response = await request.close();
} finally {
Map<String, dynamic> requestHeader = {};
Map<String, dynamic> responseHeader = {};
request!.headers.forEach((name, values) {
requestHeader[name] = values;
});
var responseBody = "";
if (response != null) {
response.headers.forEach((name, values) {
responseHeader[name] = values;
});
responseBody = await response.transform(Utf8Decoder()).join();
}
FTRUMManager().stopResource(key);
FTRUMManager().addResource(
key: key,
url: request.uri.toString(),
requestHeader: requestHeader,
httpMethod: request.method,
responseHeader: responseHeader,
resourceStatus: response?.statusCode,
responseBody: responseBody,
);
}
}
http라이브러리 및dio라이브러리 사용은 example을 참조하세요.