Cómo escribir y ver registros con Logcat

La ventana Logcat de Android Studio muestra los mensajes del sistema, por ejemplo, cuando se produce la recolección de elementos no utilizados, y los mensajes que agregas a tu app con la clase Log. Se muestran los mensajes en tiempo real y se conserva un historial para que puedas ver los mensajes más antiguos.

A fin de mostrar solo la información de interés, puedes crear filtros, modificar la cantidad de información que se muestra en los mensajes, establecer niveles de prioridad, mostrar los mensajes generados únicamente por el código de la app y realizar búsquedas en el registro. De forma predeterminada, Logcat solo muestra el resultado del registro relacionado con la última app que se ejecutó.

Si la app genera una excepción, Logcat muestra un mensaje y, a continuación, el seguimiento de pila que contiene los vínculos a la línea de código.

En la ventana de ejecución, se muestran los mensajes de registro de la app que se esté ejecutando en el momento. Puedes configurar la visualización de los resultados de Logcat, pero no la ventana de ejecución.

Cómo ver los registros de tu app

Para ver los mensajes del registro de una app, haz lo siguiente:

  1. Compila y ejecuta la app en un dispositivo.
  2. Haz clic en View > Tool Windows > Logcat (o en Logcat en la barra de ventanas de herramientas).

En la ventana Logcat se muestran los mensajes de registro de la app que se seleccionaron en el menú ubicado en la parte superior de la ventana, como se ve en la figura 1.

Figura 1: La ventana Logcat

De forma predeterminada, Logcat muestra solamente los mensajes del registro de la app que se esté ejecutando en el dispositivo. Para cambiar este valor predeterminado, consulta cómo filtrar los mensajes de Logcat.

En la barra de herramientas de Logcat, se incluyen los siguientes botones:

  1. Clear Logcat : Haz clic en esta opción para borrar el registro visible.
  2. Scroll to the end : Haz clic en esta opción para saltar a la parte inferior del registro y ver los últimos mensajes. Si luego haces clic en una línea del registro, se detendrá el desplazamiento de la vista en ese punto.
  3. Up the stack trace y Down the stack trace : Haz clic en estas opciones para navegar hacia arriba y hacia abajo por los seguimientos de pila del registro, y selecciona el nombre de archivo anterior o siguiente que aparece en las excepciones impresas. Este comportamiento es el mismo que se genera cuando haces clic en un nombre de archivo del registro.
  4. Use soft wraps : Haz clic en esta opción para habilitar el ajuste de línea y evitar el desplazamiento horizontal. Sin embargo, es posible que las strings no separables sigan requiriendo un desplazamiento horizontal.
  5. Print : Haz clic en esta opción para imprimir los mensajes de Logcat. Una vez que hayas seleccionado tus preferencias de impresión en el cuadro de diálogo que aparece, podrás elegir guardar los mensajes como PDF.
  6. Restart : Haz clic en esta opción para borrar el registro y reiniciar Logcat. A diferencia del botón Clear Logcat, este botón recupera y muestra los mensajes anteriores del registro, de modo que es muy útil si Logcat no responde y no quieres perder los mensajes.
  7. Logcat header : Haz clic en esta opción para abrir el diálogo Configure Logcat Header, donde puedes personalizar la apariencia de los mensajes de Logcat, por ejemplo, si quieres que se muestren la fecha y la hora.
  8. Screen capture : Haz clic en esta opción para tomar una captura de pantalla.
  9. Screen record : Haz clic en esta opción para grabar un video del dispositivo durante un máximo de 3 minutos.

Cómo escribir mensajes de registro

La clase Log te permite crear mensajes de registro que aparecerán en Logcat. Todos los mensajes de registro de Android tienen una etiqueta y una prioridad asociadas a ellos. La etiqueta de un mensaje de registro del sistema es una string breve que indica el componente del sistema a partir del cual se origina el mensaje.

Usa los siguientes métodos de acceso, ordenados de mayor a menor prioridad:

Una etiqueta definida por el usuario puede ser cualquier string que te resulte útil, como el nombre de la clase actual. Defines la etiqueta en una llamada al método Log, por ejemplo:

Kotlin

Log.d(tag, message)

Java

Log.d(tag, message);

Consulta la descripción de la clase Log para obtener una lista más completa de opciones.

Nunca compiles registros detallados en tu app, excepto durante el desarrollo. Los registros de depuración se compilan, pero se quitan durante el tiempo de ejecución. Los registros de error, advertencia e información se conservan siempre.

Para cada método de registro, el primer parámetro debe ser una etiqueta exclusiva, mientras que el segundo es el mensaje. La etiqueta de un mensaje de registro del sistema es una string breve que indica el componente del sistema a partir del cual se origina el mensaje. Tu etiqueta puede ser cualquier string que te resulte útil; por ejemplo, el nombre de la clase actual.

Una buena convención es declarar una constante TAG en tu clase para usarla en el primer parámetro. Por ejemplo, puedes crear un mensaje de registro de información de la siguiente manera:

Kotlin

private const val TAG = "MyActivity"
...
Log.i(TAG, "MyClass.getView() — get item number $position")

Java

private static final String TAG = "MyActivity";
...
Log.i(TAG, "MyClass.getView() — get item number " + position);

Nota: Los nombres de etiquetas con más de 23 caracteres aparecerán truncados en el resultado de Logcat.

Formato de mensajes de Logcat

El formato del mensaje de registro es el siguiente:

date time PID-TID/package
priority/tag: message

PID significa "identificador de proceso", y TID, "identificador de subproceso". Si hay un solo subproceso, ambos pueden ser iguales.

Por ejemplo, el siguiente mensaje de registro tiene la prioridad V y una etiqueta AuthZen:

12-10 13:02:50.071 1901-4229/com.google.android.gms V/AuthZen: Handling delegate intent.

Cómo establecer el nivel de registro

Puedes configurar el nivel de registro para controlar si Logcat muestra todos los mensajes o solo aquellos que indican las condiciones más graves.

Logcat continuará recopilando todos los mensajes, independientemente de la configuración del nivel de registro. Este ajuste solo determina qué mostrará Logcat.

En el menú de nivel de registro, selecciona uno de los siguientes valores:

  • Verbose: Se muestran todos los mensajes del registro (configuración predeterminada).
  • Debug: Se muestran los mensajes del registro que son útiles solo para la etapa de desarrollo, además de los niveles de mensajes de la parte inferior de la lista.
  • Info: Se muestran los mensajes de registro esperados para uso normal, además de los niveles de mensajes de la parte inferior de la lista.
  • Warn: Se muestran los posibles problemas que aún no causaron errores, además de los niveles de mensajes de la parte inferior de la lista.
  • Error: Se muestran los problemas que causaron errores, además de los niveles de mensajes de la parte inferior de la lista.
  • Assert: Se muestran los problemas que el desarrollador cree que no ocurrirán en ningún momento.

Cómo buscar mensajes en Logcat

Para buscar los mensajes que se muestran actualmente en Logcat, puedes hacer lo siguiente:

  1. (Opcional) Selecciona Regex si quieres usar un patrón de búsqueda de expresiones regulares.
  2. Escribe una secuencia de caracteres en el campo de búsqueda .

    La pantalla de resultados de Logcat cambiará según corresponda.

  3. Presiona Intro para almacenar la string de búsqueda en el menú durante esta sesión.
  4. Para repetir una búsqueda, selecciónala en el menú de búsqueda. Selecciona Regex o anula su selección según sea necesario.

Cómo filtrar mensajes en Logcat

Una forma de reducir los resultados del registro a un nivel razonable es restringirlos mediante un filtro.

Nota: El filtro se aplica a todo el historial de Logcat, no solo a los mensajes que se muestran actualmente. Asegúrate de que las demás opciones de visualización estén configuradas de forma adecuada, de modo que puedas ver el resultado del filtro que quieras examinar.

Para definir y aplicar un filtro, sigue estos pasos:

  1. En el menú de filtros, selecciona una opción de filtro:
    • Show only selected application: Muestra solo los mensajes generados por el código de la app (configuración predeterminada). Logcat filtra los mensajes del registro mediante el PID de la app activa.
    • No Filters: No se aplica ningún filtro. Logcat muestra todos los mensajes del registro del dispositivo, independientemente del proceso seleccionado.
    • Edit Filter Configuration: Permite crear o modificar un filtro personalizado. Por ejemplo, puedes crear un filtro para ver los mensajes del registro de dos apps al mismo tiempo.

    Una vez definidos los filtros, también puedes seleccionarlos en el menú. Para quitarlos del menú, debes borrarlos.

  2. Si seleccionaste Edit Filter Configuration, crea o modifica un filtro:
    1. En la ventana de diálogo Create New Logcat Filter, especifica los parámetros del filtro:
      • Filter Name: Ingresa el nombre del filtro que desees definir o selecciona uno del panel izquierdo para modificarlo. El nombre solamente puede contener caracteres en minúscula, guiones bajos y números.
      • Log Tag: Permite especificar una etiqueta de manera opcional.
      • Log Message: Permite especificar un texto de mensaje de registro de manera opcional.
      • Package Name: Permite especificar un nombre de paquete de manera opcional.
      • PID: Puedes especificar un ID de proceso de manera opcional.
      • Log Level: Permite seleccionar un nivel de registro de manera opcional.
      • Regex: Selecciona esta opción a fin de usar la sintaxis de expresiones regulares para el parámetro.
    2. Haz clic en + para agregar la definición del filtro al panel izquierdo.

      Para quitar un filtro, selecciónalo en el panel izquierdo y haz clic en -.

    3. Cuando hayas terminado, haz clic en OK.

Si no ves los mensajes de registro que deseas, selecciona No filters y busca mensajes de registro específicos.

Cómo leer mensajes de recolección de elementos no utilizados

A veces, cuando se produce un evento de recolección de elementos no utilizados (GC), la información se imprime en Logcat.

Para obtener más información de la memoria de la app, usa el Generador de perfiles de memoria.

Mensajes del registro de Dalvik

En Dalvik, pero no en ART, todas las recolecciones de elementos no utilizados envían la siguiente información a Logcat:

D/dalvikvm(PID): GC_Reason Amount_freed,
Heap_stats, External_memory_stats, Pause_time

Ejemplo:

D/dalvikvm( 9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2ms

Mientras se acumulan los mensajes de registro, busca aumentos en las estadísticas del montón. Si este valor continúa aumentando, es posible que haya una fuga de memoria.

Los siguientes términos se incluyen en los mensajes del registro de Dalvik:

Motivo de la recolección de elementos no utilizados
Indica qué activó la recolección y el tipo de recopilación. Entre los motivos que pueden aparecer, se incluyen los siguientes:
GC_CONCURRENT
Es una recolección de elementos no utilizados simultánea que libera memoria cuando se inicia el montón para completarlo.
GC_FOR_MALLOC
Se generó una recolección de elementos no utilizados porque la app intentó asignar memoria cuando el montón ya estaba completo, por lo que el sistema tuvo que detener la app y reclamar memoria.
GC_HPROF_DUMP_HEAP
Se genera una recolección de elementos no utilizados cuando solicitas crear un archivo HPROF para analizar el montón.
GC_EXPLICIT
Es una recolección de elementos no utilizados explícita, por ejemplo, cuando llamas a gc(). Sin embargo, evita llamar a este método. En su lugar, confía en que se ejecutará la recolección de elementos no utilizados cuando sea necesario.
GC_EXTERNAL_ALLOC
Es una recolección de elementos no utilizados para memoria asignada de manera externa; por ejemplo, los datos de píxeles almacenados en la memoria nativa o en búferes de bytes NIO. Esto solo sucede en el nivel de API 10 y niveles inferiores. Las versiones más recientes asignan todo en el montón de Dalvik.
Cantidad liberada
Es la cantidad de memoria reclamada desde esta recolección de elementos no utilizados.
Estadísticas del montón
Es el porcentaje libre del montón y (número de objetos en vivo)/(tamaño total del montón).
Estadísticas de la memoria externa
Es la memoria asignada de manera externa en el nivel de API 10 y niveles inferiores (cantidad de memoria asignada)/(límite en el que se llevará a cabo la recopilación).
Tiempo de pausa
Los montones más grandes tienen tiempos de pausa mayores. Los tiempos de pausa simultáneos muestran dos pausas: una al inicio de la recopilación y otra cerca del final.

Mensajes del registro de ART

A diferencia de Dalvik, ART no registra mensajes para las recolecciones de elementos no utilizados que no se solicitaron de forma explícita. La información de la recolección de elementos no utilizados se imprime únicamente cuando es explícita, cuando la pausa supera los 5 ms o cuando la duración supera los 100 ms. Si la app no se encuentra en estado de pausa, por ejemplo, cuando se ejecuta en segundo plano, donde el usuario no puede percibir la detención de una recolección de elementos no utilizados, no se imprime información de la recolección, excepto que sea explícita.

ART incluye la siguiente información en los mensajes de registro de recolección de elementos no utilizados:

I/art: GC_Reason GC_Name Objects_freed(Size_freed) AllocSpace Objects,
    Large_objects_freed(Large_object_size_freed) Heap_stats LOS objects, Pause_time(s)

Ejemplo:

I/art : Explicit concurrent mark sweep GC freed 104710(7MB) AllocSpace objects,
    21(416KB) LOS objects, 33% free, 25MB/38MB, paused 1.230ms total 67.216ms

Se incluyen los siguientes términos en los mensajes de registro de ART:

Motivo de la recolección de elementos no utilizados
Indica qué activó la recolección y el tipo de recopilación. Entre los motivos que pueden aparecer, se incluyen los siguientes:
Concurrent
Se trata de una recolección de elementos no utilizados que no suspende los subprocesos de la app. Esta recolección se ejecuta en un subproceso en segundo plano y no evita que se realicen asignaciones.
Alloc
Se inició una recolección de elementos no utilizados porque la app intentó asignar memoria cuando la pila ya estaba llena. En este caso, la recolección tuvo lugar en el subproceso de asignación.
Explicit
Una app solicitó de manera explícita la recolección de elementos no utilizados, por ejemplo, mediante la llamada a System.gc() o Runtime.gc(). Sin embargo, como sucede con Dalvik, en ART se recomienda confiar en la recolección y, si es posible, evitar la solicitud de recolecciones explícitas. No se aconseja usar recolecciones explícitas, ya que bloquean el subproceso de asignación y se desperdician ciclos de la CPU de manera innecesaria. También pueden ocasionar bloqueos (interrupción de flujo, inestabilidad o detenciones de la app) si interrumpen la activación de otros subprocesos.
NativeAlloc
Es una recolección de elementos no utilizados causada por la presión de la memoria nativa de las asignaciones nativas, como mapas de bits u objetos de asignación RenderScript.
CollectorTransition
Se genera una recolección de elementos no utilizados debido a una transición de montón. Esto se debe a la modificación de la estrategia de recolección durante el tiempo de ejecución, por ejemplo, cuando la app cambia entre estados de detención perceptible. Las transiciones del recolector consisten en copiar todos los objetos de un espacio de copia de seguridad de listas libre a un espacio de puntero separado o viceversa.

Esto ocurre únicamente en dispositivos con poca RAM que ejecutan una versión de Android anterior a la 8.0 cuando una app cambia los estados del proceso desde un estado de detención perceptible, como cuando la app se encuentra en primer plano, donde el usuario puede percibir una pausa de recolección de elementos no utilizados, un estado de detención no perceptible, o viceversa.

HomogeneousSpaceCompact
La compactación espacial homogénea consiste en la compactación de un espacio de listas libre que, por lo general, ocurre cuando una app pasa a un estado de proceso de detención imperceptible. Esta acción se realiza principalmente para reducir el uso de la RAM y desfragmentar el montón.
DisableMovingGc
Esto no constituye un motivo de recolección de elementos no utilizados, sino una nota que indica que se bloqueó la recopilación debido al uso de GetPrimitiveArrayCritical durante la compactación simultánea del montón. En general, no se aconseja usar GetPrimitiveArrayCritical debido a las restricciones que plantea para el movimiento de los recolectores.
HeapTrim
Esto no constituye un motivo de recolección de elementos no utilizados, sino una nota que indica que se bloqueó la recopilación hasta que finalizó el corte del montón.
Nombre de la recolección de elementos no utilizados
El ART tiene varias recolecciones que pueden ejecutarse:
Concurrent mark sweep (CMS)
Es un recolector de montón completo que recopila todos los espacios, excepto los de imágenes.
Concurrent partial mark sweep
Es un recolector de montón completo que realiza recopilaciones en todos los espacios, excepto en los de imágenes y Zygote.
Concurrent sticky mark sweep
Es un recolector generacional que solo puede liberar los objetos asignados después de la última recolección. Esta recolección de elementos no utilizados se ejecuta con mayor frecuencia que un esquema de “marcar y limpiar” total o parcial, debido a que es más rápida y tiene pausas menos prolongadas.
Marksweep + semispace
Es una recolección de copia no simultánea que se usa para transiciones de montón, compactación de espacios homogéneos y para desfragmentar el montón.
Objetos liberados
Es la cantidad de objetos reclamados desde esta recolección del espacio de objetos pequeños.
Tamaño liberado
Es la cantidad de bytes reclamados desde esta recolección del espacio de objetos pequeños.
Objetos grandes liberados
Es la cantidad de objetos reclamados desde esta recolección del espacio de objetos grandes.
Tamaño de objetos grandes liberado
Es la cantidad de bytes en el espacio de objetos grandes que se reclamaron desde esta recolección.
Estadísticas del montón
Porcentaje libre y (cantidad de objetos activos)/(tamaño total del montón).
Tiempos de pausa
En general, los tiempos de detención son proporcionales al número de referencias de objetos que se modificaron mientras se ejecutaba la recolección. Actualmente, las recolecciones de CMS de ART solo tienen una detención, cerca del final de la recolección. Las recolecciones en movimiento tienen una detención larga, que dura la mayor parte del tiempo de la recolección.

Si ves una gran cantidad de mensajes de recolección en Logcat, busca aumentos en las estadísticas del montón. Si este valor continúa aumentando y no parece disminuir, es posible que haya una fuga de memoria.

Como alternativa, si ves recolecciones que especifican el motivo "Alloc", ya estás cerca de alcanzar la capacidad del montón y puedes esperar excepciones por falta de memoria en un futuro cercano.