RUM 구성¶
RUM 초기화 구성¶
| 필드 | 유형 | 필수 | 설명 |
|---|---|---|---|
| androidAppId | String | Android 필수 | Android 플랫폼의 app_id로, 애플리케이션 액세스 모니터링 콘솔에서 신청합니다. Android 런타임에서만 읽습니다. |
| iOSAppId | String | iOS 필수 | iOS 플랫폼의 app_id로, 애플리케이션 액세스 모니터링 콘솔에서 신청합니다. 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¶
startAction와 addAction의 사용 차이
startAction은 내부적으로 Action 소요 시간을 자동 계산하며, 계산하는 동안 주변에서 발생한Resource,LongTask,Error데이터와 가능한 한 연관을 시도하고 100ms 빈번 트리거 보호가 설정되어 있습니다. 사용자 작업 유형의 데이터에 권장됩니다.- 빈번하게 호출해야 한다면
addAction을 사용하세요.addAction으로 보고된 Action은startAction과 충돌하지 않으며 현재Resource,LongTask,Error데이터와도 연관되지 않습니다.
사용 방법¶
/// 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가 해당 값을 우선적으로 가져옵니다. 이 방법은 showDialog(), showTimePicker() 등 Dialog 유형 페이지에도 동일하게 적용됩니다.
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을 참조하세요.