Al desarrollar una aplicación moderna, el registro debe estar en lo más alto de la lista de prioridades.

El registro proporciona una forma de visualizar tu aplicación tanto en desarrollo como en producción, permitiendo transparencia y visibilidad. Con un registro bien estructurado, las aplicaciones modernas pueden ser más fáciles de mantener, ya que podemos identificar de forma proactiva los puntos de fallo y los cuellos de botella en el rendimiento de nuestra aplicación.

El framework Laravel viene con un robusto sistema de registro que maneja todos los obstáculos que implica la configuración de un sistema de registro correctamente estructurado desde el principio. Este nuevo sistema de registro introducido en Laravel 6.5 es potente, y lo exploraremos en este artículo.

Este artículo explorará los fundamentos del registro de Laravel y por qué deberías utilizar el registro de Laravel en tu próximo proyecto. Hablaremos en detalle del registro estructurado y del registro centralizado. Además, aprenderemos a implementar el registro de Laravel construyendo una aplicación Todo.

Sacarás más provecho de este artículo si ya tienes:

¿Qué es el Registro de Laravel?

El registro de Laravel trata de cómo Laravel gestiona el registro, o la notificación automática de problemas, utilizando un sistema de registro viral de PHP llamado Monolog. Sin embargo, debido a la filosofía de Laravel de utilizar librerías populares existentes para implementar diferentes características del framework, Laravel emplea Monolog para todas sus necesidades de registro.

Monolog es una biblioteca de registro de PHP muy flexible y popular que podemos configurar para enviar sus registros a archivos, sockets, bases de datos y otros servicios web. Monolog proporciona una interfaz familiar para escribir registros desde archivos de texto estándar hasta servicios avanzados de gestión de registros de terceros. Laravel suele configurar Monolog para que utilice un archivo de configuración de registro estándar.

Para obtener más información sobre Monolog y sus características, consulta la documentación oficial, ya que está fuera del alcance de este artículo.

Antes de sumergirnos en la configuración e implementación del registro de Laravel mediante Monolog, vamos a explorar más razones para utilizar el registro de Laravel y los diferentes tipos.

¿Por Qué Utilizar el Registro de Laravel?

¿Por qué es necesario el registro?

El manifiesto de las Apps de 12 Factores trata el registro como una de las preocupaciones críticas de una aplicación moderna, ya que el registro es clave para el rendimiento y la monitorización.

Los registros ayudan a comprender en detalle los errores que se producen en producción y dónde se originan. Además, con las estructuras de registro adecuadas, se puede mostrar el usuario concreto, la acción que causó el error y la posible solución para una corrección y mantenimiento más rápidos de los errores.

El registro estructurado es un salvavidas en las aplicaciones de producción, ya que ayuda a localizar los defectos y a resolver los problemas en producción. Además, puedes supervisar y recopilar todos tus mensajes de registro en tiempo real utilizando herramientas de registro especializadas para realizar análisis e informes en directo.

Por estas razones, debes hacer del registro estructurado una prioridad en tu próximo proyecto de aplicación moderna.

Veamos un resumen de los diferentes estilos de registro disponibles.

Fundamentos del Registro en Laravel

Aprender los fundamentos del registro te ayudará a entender cómo maneja Laravel el registro y cómo puedes mejorar tus prácticas de registro estructurado.

Examinemos dos conceptos esenciales del registro para entender mejor cómo implementar nuestros procedimientos de registro.

Registro Estructurado de Laravel

En el desarrollo de software, el registro estructurado consiste en implementar un formato de mensaje predeterminado y coherente para los registros de la aplicación. Este formato permite tratar los mensajes como datos que pueden ser monitorizados, manipulados y visualizados mucho mejor que el formato de texto normal.

Debes implementar un enfoque de registro estructurado en el desarrollo de tu aplicación moderna, porque los archivos de registro son los activos esenciales para los desarrolladores cuando algo malo le ocurre a tu aplicación en producción.

Como Laravel utiliza Monolog, los desarrolladores pueden implementar rápidamente el registro estructurado configurando el registrador para recibir tipos específicos de información, almacenando los archivos de registro en diferentes formatos y enviando los registros a varios servicios de gestión de registros de terceros para su visualización.

Registro Centralizado de Laravel

Un sistema de registro centralizado es aquel en el que los registros se envían a soluciones de gestión centralizada de registros (CLM) desde múltiples fuentes para facilitar su consolidación y visualización. Sin embargo, CLM es una solución de registro especializada que recoge los mensajes de registro de diferentes fuentes y consolida los datos para facilitar su procesamiento y visualización.

Además de la recopilación de datos, se espera que el CLM también apoye el análisis de los datos de registro y la presentación clara de los datos después del análisis.

Registro Estructurado Frente a Registro Básico

Examinemos la diferencia entre el registro estructurado y el registro básico (no estructurado) y por qué deberías utilizar el registro estructurado en tu proyecto Laravel.

Registro Básico

En el registro básico, los archivos de registro se almacenan en un formato crudo con datos limitados para consultar e identificar registros individuales.

Al utilizar el registro básico, los desarrolladores no podrán utilizar herramientas analíticas de terceros para leer, ver y analizar los registros, a menos que desarrollen una herramienta personalizada o se queden con una herramienta limitada que soporte su formato de registro.

Hay tres grandes razones para evitar el uso del registro básico:

  1. Los sistemas centralizados de gestión de registros no pueden trabajar con los datos sin apoyo adicional.
  2. Se necesita una solución personalizada para leer y analizar los datos de una solución de registro básica.
  3. Puede ser un reto para los administradores leer los datos de registro básicos, ya que son crudos y no están estructurados.

Registro Estructurado

El registro estructurado ahorra tiempo a los desarrolladores al utilizar herramientas analíticas de registro de terceros de código abierto que admiten la estructura de registro estándar para leer, ver y analizar los registros.

Los registros son útiles si contienen los datos correctos que se indican a continuación, que es lo que pretende el registro estructurado. Podemos utilizar los datos incluidos en el registro estructurado para crear cuadros de mando, gráficos, diagramas y cualquier otra visualización útil para determinar la salud de la aplicación.

Estos son ejemplos básicos de la información que podemos incluir en los mensajes de registro estructurado. Además, puedes personalizar completamente los datos para adaptarlos a tus necesidades.

Estos son algunos ejemplos de los datos que puedes recoger con el registro estructurado:

  1. El puerto utilizado para ejecutar la función
  2. La fecha y hora en que se produjo el evento
  3. El nombre de usuario o ID del cliente
  4. Una descripción del evento (mensaje de registro)
  5. El protocolo utilizado para ejecutar la función
  6. La ubicación del evento desencadenado (indica la API o la aplicación en ejecución)
  7. El identificador único del evento
  8. El tipo de acción desencadenada (nivel de registro)

Los registros deben contener suficientes datos para visualizar fácilmente la solución o el motivo del evento de registro. Además, ten en cuenta que no debes almacenar en los registros todo tipo de información, como contraseñas o datos sensibles.

Ahora que hemos vislumbrado en qué consiste el registro de Laravel, pasemos a implementar el registro de Laravel construyendo una aplicación con el registro como ciudadano de primera clase.

¿Cómo Implementar el Registro de Laravel con Todo App?

Ahora vamos a aplicar lo que hemos aprendido hasta ahora creando un nuevo proyecto Laravel e implementando el registro Laravel.

Si no has usado Laravel antes, puedes leer ¿qué es Laravel? o echar un vistazo a nuestra lista de excelentes tutoriales de Laravel para empezar.

Configurar Laravel

En primer lugar, vamos a crear una nueva instancia de Laravel utilizando el siguiente comando. Puedes consultar la documentación oficial para saber más.

Abre tu consola y navega hasta el lugar donde guardas tus proyectos PHP antes de ejecutar los comandos siguientes. Asegúrate de tener instalado y configurado correctamente Composer.

composer create-project laravel/laravel laravel-logging-app
cd laravel-logging-app // Change directory to current Laravel installation
php artisan serve // Start Laravel development server

Configurar y Sembrar la Base de Datos

A continuación, configuraremos nuestra base de datos, crearemos un nuevo modelo Todo y sembraremos 200 datos falsos para las pruebas.

Abre tu cliente de base de datos y crea una nueva base de datos. Haremos lo mismo con el nombre laravel_logging_app_db y luego rellenaremos nuestro archivo .env con las credenciales de la base de datos:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_logging_app_db
DB_USERNAME=//DB USERNAME HERE
DB_PASSWORD=//DB PASSWORD HERE

A continuación, ejecutaremos el siguiente comando para crear la migración y el modelo Todo simultáneamente:

php artisan make:model Todo -mc

Abre la migración recién creada encontrada database/migrations/xxx-create-todos-xxx.php y pega los siguientes códigos:

<?php
use IlluminateSupportFacadesSchema;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;
class CreateTodosTable extends Migration
{
  /**
  * Run the migrations.
  *
  * @return void
  */
  public function up()
  {
    Schema::create('todos', function (Blueprint $table) {
      $table->id();
      $table->string('title');
      $table->text('description')->nullable();
      $table->boolean('is_completed')->default(false);
      $table->timestamps();
    });
  }
  /**
  * Reverse the migrations.
  *
  * @return void
  */
  public function down()
  {
    Schema::dropIfExists('todos');
  }
}

Puedes sembrar tus todos con datos de Faker aprendiendo a sembrar tus bases de datos en Laravel utilizando Faker.

Visión General de Monolog

Con Laravel Monolog, puedes transmitir y enviar registros estructurados a diferentes canales como correos electrónicos, Slack, archivos, sockets, bandejas de entrada, bases de datos y varios servicios web. En Laravel, puedes configurar el registro desde un único archivo de configuración situado en config/logging.php.

El archivo de configuración viene con controladores de registro predefinidos para elegir, y el controlador por defecto es un stack que utiliza el canal single para registrar en un archivo laravel.log que se encuentra en la carpeta storage/logs. Vamos a demostrar el registro estructurado utilizando un par de controladores de registro de Laravel.

Laravel proporciona un puñado de métodos para interactuar con los logs, como se demuestra en general en el archivo controlador TodosController. php en breve.

Escribir Mensajes de Registro en el Controlador

Abre el archivo controlador TodosController.php recién creado que se encuentra en la carpeta app/Http/Controllers y pega los siguientes códigos:


<?php
namespace AppHttpControllers;
use AppModelsTodo;
use IlluminateHttpRequest;
use AppHttpControllersController;
use IlluminateSupportFacadesAuth;
use IlluminateSupportFacadesLog;
class TodosController extends Controller
{
  public function index(Request $request)
  {
    $todos = Todo::all();
    Log::warning('User is accessing all the Todos', ['user' => Auth::user()->id]);
    return view('dashboard')->with(['todos' => $todos]);
  }
  public function byUserId(Request $request)
  {
    $todos = Todo::where('user_id', Auth::user()->id)->get();
    Log::info('User is accessing all his todos', ['user' => Auth::user()->id]);
    return view('dashboard')->with(['todos' => $todos]);
  }
  public function show(Request $request, $id)
  {
    $todo = Todo::find($id);
    Log::info('User is accessing a single todo', ['user' => Auth::user()->id, 'todo' => $todo->id]);
    return view('show')->with(['todo' => $todo]);
  }
  public function update(Request $request, $id)
  {
    # Validations before updating
    $todo = Todo::where('user_id', Auth::user()->id)->where('id', $id)->first();
    Log::warning('Todo found for updating by user', ['user' => Auth::user()->id, 'todo' => $todo]);
    if ($todo) {
      $todo->title = $request->title;
      $todo->desc = $request->desc;
      $todo->status = $request->status == 'on' ? 1 : 0;
      if ($todo->save()) {
        Log::info('Todo updated by user successfully', ['user' => Auth::user()->id, 'todo' => $todo->id]);
        return view('show', ['todo' => $todo]);
      }
      Log::warning('Todo could not be updated caused by invalid todo data', ['user' => Auth::user()->id, 'todo' => $todo->id, 'data' => $request->except('password')]);
      return; // 422
    }
    Log::error('Todo not found by user', ['user' => Auth::user()->id, 'todo' => $id]);
    return; // 401
  }
  public function store(Request $request)
  {
    Log::warning('User is trying to create a single todo', ['user' => Auth::user()->id, 'data' => $request->except('password')]);
    # Validations before updating
    $todo = new Todo;
    $todo->title = $request->title;
    $todo->desc = $request->desc;
    $todo->user_id = Auth::user()->id;
    if ($todo->save()) {
      Log::info('User create a single todo successfully', ['user' => Auth::user()->id, 'todo' => $todo->id]);
      return view('show', ['todo' => $todo]);
    }
    Log::warning('Todo could not be created caused by invalid todo data', ['user' => Auth::user()->id, 'data' => $request->except('password')]);
    return; // 422
  }
  public function delete(Request $request, $id)
  {
    Log::warning('User is trying to delete a single todo', ['user' => Auth::user()->id, 'todo' => $id]);
    $todo = Todo::where('user_id', Auth::user()->id)->where('id', $id)->first();
    if ($todo) {
      Log::info('User deleted a single todo successfully', ['user' => Auth::user()->id, 'todo' => $id]);
      $todo->delete();
      return view('index');
    }
    Log::error('Todo not found by user for deleting', ['user' => Auth::user()->id, 'todo' => $id]);
    return; // 404
  }
}

Dentro de cada uno de los métodos del TodoController, añadimos la fachada Log con un nivel de registro específico para definir el tipo de error que queremos enviar. A continuación se muestra un ejemplo de uso del

Fachada de registro en el método store.

public function store(Request $request)
{
  Log::warning('User is trying to create a single todo', ['user' => Auth::user()->id, 'data' => $request->except('password')]);
  # Validations before updating
  $todo = new Todo;
  $todo->title = $request->title;
  $todo->desc = $request->desc;
  $todo->user_id = Auth::user()->id;
  if ($todo->save()) {
    Log::info('User create a single todo successfully', ['user' => Auth::user()->id, 'todo' => $todo->id]);
    return view('show', ['todo' => $todo]);
  }
  Log::warning('Todo could not be created caused by invalid todo data', ['user' => Auth::user()->id, 'data' => $request->except('password')]);
  return; // 422
}

Formatear los Mensajes de Registro

Supón que no te sientes cómodo con el LineFormatter por defecto utilizado por Laravel, que hace un gran trabajo para proporcionar mensajes legibles y útiles.

En ese caso, puedes crear fácilmente un objeto formateador personalizado que se adapte a tu caso de uso y utilizarlo en toda la aplicación.

La documentación oficial de Monolog ofrece una lista completa de los formateadores disponibles y puedes crear fácilmente uno personalizado.

En Laravel, puedes configurar fácilmente cualquiera de los controladores para que utilicen tu formateador personalizado añadiéndolo a la lista como se indica a continuación dentro del archivo de configuración situado en config/logging.php:

'daily' => [
  'driver' => 'daily',
  'path' => storage_path('logs/laravel.log'),
  'level' => env('LOG_LEVEL', 'debug'),
  'days' => 14,
  'formatter' => MonologFormatterHtmlFormatter::class,
  'formatter_with' => [
    'dateFormat' => 'Y-m-d',
  ]
],

El ejemplo anterior añade un MonologFormatterHtmlFormatter personalizado al controlador daily utilizando la clave formatter y formatter_with en la configuración del canal daily para cambiar el formato de las fechas.

Envío de Registros a Diferentes Canales

Con la ayuda de Monolog, Laravel puede enviar registros a diferentes canales y a varios canales simultáneamente.

Vamos a demostrar cómo enviar registros a nuestro canal de Slack siguiendo estos sencillos pasos. Cambia el canal de registro por defecto a Slack y añade la URL de Slack Webhook en tu archivo .env.

LOG_CHANNEL=slack
LOG_SLACK_WEBBHOOK_URL= Slack_webhook_url_here

A continuación, prueba tu configuración registrando un mensaje en tu aplicación utilizando la fachada Log como la que se muestra a continuación:

Log::debug("The API instance is on fire caused by:", ['user' => 1])

Puedes abrir tu canal de Slack para comprobar el error impreso en el canal deseado que hayas especificado al generar la URL del Webhook.

Resumen

El registro es tan importante como cualquier otro factor de tu aplicación, si no más. Por eso se sugiere en el manifiesto de los Doce Factores de la App como una de las preocupaciones más críticas de cualquier aplicación moderna.

Con un registro eficaz, puedes leer, ver y visualizar fácilmente los errores y defectos que se produzcan en tu aplicación lista para la producción. Para ello, es importante que implementes un registro estructurado en tu aplicación desde el inicio del proyecto.

En este artículo, hemos explorado el registro de Laravel y por qué deberías utilizarlo en tu próximo proyecto. Hemos hablado en detalle del registro estructurado y del registro centralizado. Además, hemos aprendido a implementar el registro de Laravel construyendo una aplicación Todo.

¿Cómo piensas implementar el registro en tu próxima aplicación? Háznoslo saber en la sección de comentarios.

Solomon Eseme

I am a Software Engineer and Content Creator who is geared toward building high-performing and innovative products following best practices and industry standards. I also love writing about it at Masteringbackend.com. Follow me on Twitter, LinkedIn, and About Me