Información general

React Native es un marco de JavaScript para desarrollar aplicaciones móviles híbridas que pueden ejecutarse de forma nativa tanto en Android como en iOS.

Si tienes una aplicación híbrida que está creada sobre React Native, puedes usar Datadog para monitorizar la misma aplicación tanto desde el lado nativo de Android o iOS como desde el lado de React Native.

Los eventos RUM de ambas fuentes se notifican como procedentes de la misma aplicación y la misma fuente en Datadog RUM.

Limitaciones

  • Para el rastreo de errores, recursos e interacciones, los SDKs pueden funcionar de las siguientes maneras:
    • A través de la Instrumentación automática: algunas clases y métodos de React se modifican para automatizar esto. La instrumentación automática para errores, recursos e interacciones de JavaScript solo se puede iniciar desde el código de JavaScript.
    • A través de la Instrumentación manual: por ejemplo, si quieres informar de algo que consideras un error, pero que no va a colapsar la aplicación.
  • Puedes compartir la misma instancia del SDK central entre nativo y React Native sin tener que inicializar el SDK en ambos lados por separado. Esto te permite inicializar el SDK nativo en el lado nativo o en el lado de React Native (llamando a DdSdkReactNative.initialize) y tenerlo inicializado para ambos lados, con eventos en la misma sesión RUM. React Native usa la instancia central por defecto. Esto significa que puedes usar la Instrumentación manual en ambos lados, pero la Instrumentación automática solo se activa para el lado en el que se inicializó el SDK.
  • Puedes informar de eventos o logs de Datadog RUM solo después de la inicialización. Si aún no has inicializado el SDK, eventos y logs no se envían.
  • No puedes cambiar el atributo de fuente de una sesión RUM; todos tus eventos RUM aparecen bajo la misma fuente.

Monitorización de aplicaciones React Native con contenido nativo

Antes de que puedas empezar la monitorización de aplicaciones React Native con contenido nativo, necesitas inicializar el SDK de React Native.

Inicializar el SDK de React Native

Para inicializar el SDK tanto en React Native como en el lado nativo, puedes seguir la documentación de monitorización de React Native.

Con esta configuración, puedes llamar a los SDKs nativos y de React Native para logs, trazas (traces) y RUM.

Recomendamos esta solución si no has utilizado nuestro SDK en el lado nativo antes de inicializarlo en el lado de React Native.

En Android, añade los SDKs de Datadog Android a tus dependencias en tu archivo android/app/build.gradle:

// La versión se establece por @datadog/mobile-react-native
implementation "com.datadoghq:dd-sdk-android-rum"
implementation "com.datadoghq:dd-sdk-android-logs"
implementation "com.datadoghq:dd-sdk-android-trace"
implementation "com.datadoghq:dd-sdk-android-webview"

En iOS, añade los SDKs de iOS Datadog a tus dependencias en tu archivo ios/Podfile para utilizarlos en archivos Objective C:

# Asegúrate de que la versión coincide con la de node_modules/@datadog/mobile-react-native/DatadogSDKReactNative.podspec
pod 'DatadogSDKObjc', '~> 2.5.0'

Rastreo de las visitas nativas de RUM

Si utilizas una biblioteca de navegación para tu aplicación React Native como react-navigation, al utilizar la opción de configuración nativeViewTracking se crean muchas vistas duplicadas.

Si este es el caso, rastrea tus Vistas RUM nativas manualmente. Consulta la documentación para iOS y para Android.

Rastreo de los recursos nativos de RUM

Si has habilitado el rastreo con tu backend, los hosts de origen para tus recursos RUM nativos son los mismos que para tus recursos RUM de React Native.

Si utilizas OkHttp, puedes utilizar el interceptor de Datadog para rastrear automáticamente las solicitudes de red. Alternativamente, puedes rastrear manualmente los recursos.

Puedes realizar un rastreo de las solicitudes de red mediante la monitorización de tu URLSession. Obtén más información sobre cómo realizar un rastreo automático de las solicitudes de red.

Limitaciones

Si escribes algún código nativo que dependa del SDK de Datadog, asegúrate de ejecutar ese código después de inicializar el SDK en el lado de React Native. Cuando inicializas el SDK en el lado de React Native, también se inicializa en el lado nativo.

Monitorización de aplicaciones nativas con pantallas de React Native

Antes de que puedas empezar la monitorización de aplicaciones React Native con contenido nativo, necesitas inicializar el SDK de React Native.

Inicializar el SDK de React Native

Instala el SDK de React Native Datadog con las siguientes opciones de comando:

yarn add @datadog/mobile-react-native

o

npm install @datadog/mobile-react-native

Añade el SDK de Android Datadog a tus dependencias en tu archivo android/app/build.gradle:

// La versión se establece por @datadog/mobile-react-native
implementation "com.datadoghq:dd-sdk-android-rum"
implementation "com.datadoghq:dd-sdk-android-logs"
implementation "com.datadoghq:dd-sdk-android-trace"
implementation "com.datadoghq:dd-sdk-android-webview"

Inicializa el SDK en el lado nativo. Consulta la documentación oficial de Android para obtener instrucciones.

Inicializa el SDK en el lado nativo. Consulta la documentación oficial de iOS para obtener instrucciones.

Instrumentación de vistas RUM de React Native

Utiliza un ComponentPredicate para filtrar las vistas nativas creadas por tus bibliotecas de navegación:

// Adapta el tipo de fragmento a tu estrategia de seguimiento de la vista
class RNComponentPredicate : ComponentPredicate<Fragment> {
    override fun accept(component: Fragment): Boolean {
        // Identica y suelta las vistas de pantalla de React Native
        if (component.javaClass.name.startsWith("com.swmansion.rnscreens")) {
            return false
        }
        if (component.javaClass.name.startsWith("com.facebook.react")) {
            return false
        }
        return true
    }

    override fun getViewName(component: Fragment): String? {
        return null
    }
}

// Utilízala en tu configuración RUM
rumConfiguration.useViewTrackingStrategy(FragmentViewTrackingStrategy(true, RNComponentPredicate()))

A continuación, utiliza @datadog/mobile-react-navigation para realizar un rastreo de tus vistas.

Si has activado el enmascaramiento de ProGuard, añade reglas para evitar el enmascaramiento de los paquetes de destino en las compilaciones de lanzamiento.

Utiliza un UIKitRUMViewsPredicate para filtrar las vistas nativas creadas por tus bibliotecas de navegación:

class RNHybridPredicate: UIKitRUMViewsPredicate {
    var defaultPredicate = DefaultUIKitRUMViewsPredicate()

    func rumView(for viewController: UIViewController) -> RUMView? {
        let canonicalClassName = NSStringFromClass(type(of: viewController))
        // Suelta las vistas de RN
        if (canonicalClassName.starts(with: "RN")) {
            return nil
        }

        return defaultPredicate.rumView(for: viewController)
    }
}

// Utilízala en tu configuración RUM
let rumConfiguration = RUM.Configuration(
    applicationID: applicationId,
    uiKitViewsPredicate: RNHybridPredicate(),
)

Instrumentación de errores, interacciones y recursos de React Native

Envuelve tu aplicación React Native con el componente DatadogProvider para registrar automáticamente errores, interacciones y recursos de React Native RUM:

const configuration = {
    trackResources: true,
    trackErrors: true,
    trackInteractions: true
};

const RNApp = props => {
    useEffect(() => {
        /**
         * In here we can put fake values. The only goal of this call
         * is to empty the buffer of RUM events.
         */
        DatadogProvider.initialize({
            clientToken: 'fake_value',
            env: 'fake_value',
            applicationId: 'fake_value'
        });
    }, []);
    const navigationRef = useRef(null);

    return (
        <DatadogProvider configuration={configuration}>
            {/* Content of your app goes here */}
        </DatadogProvider>
    );
};

AppRegistry.registerComponent('RNApp', () => RNApp);

Para eliminar las interacciones duplicadas en Android, filtra las interacciones de React Native en el lado nativo con un EventMapper:

class RNActionEventMapper : EventMapper<ActionEvent> {
    override fun map(event: ActionEvent): ActionEvent? {
        var targetClassName = (event.context?.additionalProperties?.get("action.target.classname") as? String)
        if(targetClassName?.startsWith("com.facebook.react") == true) {
            return null
        }
        return event
    }
}

// Utilízala en tu configuración RUM
rumConfiguration.setActionEventMapper(RNActionEventMapper())

Si has activado el enmascaramiento de ProGuard, añade reglas para evitar el enmascaramiento de los paquetes de destino en las compilaciones de lanzamiento.

Limitaciones

Si has especificado un resourceEventMapper o actionEventMapper en tu configuración de React Native, los recursos y acciones no serán eliminados si devuelves null en el asignador.

Para mantener esta funcionalidad, añade los siguientes fragmentos en tu configuración nativa para tu plataforma:

val config = RumConfiguration.Builder(applicationId = appId)
 .setResourceEventMapper(object : EventMapper<ResourceEvent> {
        override fun map(event: ResourceEvent): ResourceEvent? {
            if (event.context?.additionalProperties?.containsKey("_dd.resource.drop_resource") == true) {
                return null
            }
            // Puedes añadir tu lógica del asignador de eventos personalizada aquí
            return event
        }
    })
 .setActionEventMapper(object : EventMapper<ActionEvent> {
        override fun map(event: ActionEvent): ActionEvent? {
            if (event.context?.additionalProperties?.containsKey("_dd.action.drop_action") == true) {
                return null
            }
            // Puedes añadir tu lógica del asignador de eventos personalizada aquí
            return event
        }
    })
RUM.Configuration(
    applicationID: applicationId,
    resourceEventMapper: { resourceEvent in
        if resourceEvent.context?.contextInfo["_dd.resource.drop_resource"] != nil {
            return nil
        }
        // Puedes añadir tu lógica del asignador de eventos personalizada aquí
        return resourceEvent
    },
    actionEventMapper: { actionEvent in
        if actionEvent.context?.contextInfo["_dd.resource.drop_action"] != nil {
            return nil
        }
        // Puedes añadir tu lógica del asignador de eventos personalizada aquí
        return resourceEvent
    }
)

Referencias adicionales

Más enlaces, artículos y documentación útiles: