Está en la página 1de 127

ESTEVE GRAELLS

LA GUÍA DEFINITIVA PARA


DOMINAR EL LOG DE
SALESFORCE
En teoría, no hay diferencia entre teoría y práctica.
Pero en la práctica, sí que la hay.
La guía definitiva para dominar el Log de Salesforce

Copyright © 2020-2021 por Esteve Graells.

Reservados todos los derechos. No se permite la reproducción total o parcial de esta obra, ni su
incorporación a un sistema informático, ni su transmisión en cualquier forma o por cualquier
medio (electrónico, mecánico, fotocopia, grabación u otros) sin autorización previa y por escrito de
Esteve Graells. La infracción de dichos derechos puede constituir un delito contra la propiedad
intelectual.

Gracias por comprar una edición autorizada. Respetando este copyright respaldas y respetas mi
trabajo permitiendo que continúe publicando.

Todos los ingresos procedentes de todas las versiones de este libro, tanto en formatos
electrónicos como impresos se dedican a entidades con fines sociales.

Si tu empresa desea sponsorizar una versión de esta guía, también destinaré todos los ingresos a
estas entidades o a las que acordemos mutuamente.

Si tienes dudas o deseas saber a qué entidades se derivan los ingresos, por favor ponte en
contacto conmigo a través de Linkedin.

Si te interesa regalar este libro lo tienes disponible en Amazon: La Guía definitiva para usar el Log
de Salesforce.

Desafortunadamente no puedo garantizar que esta guía se imprima en papel reciclado, ya que se
realiza mediante impresión on Demand.

Esta es la segunda edición, donde he realizado ciertas modificaciones con el feedback recibido.
En cualquier caso, no suponen un cambio sustancial, y en ningún caso un motivo para adquirir la
segunda edición si se posee la primera.

2
Sumario

Dedicado a mi familia, sin ellos nada sería posible en mi vida.

3
La guía definitiva para dominar el Log de Salesforce

Sumario
SUMARIO ............................................................................................................................................................................. 4

1. PRÓLOGO ................................................................................................................................................................... 5

2. UN POCO DE CONTEXTO ................................................................................................................................. 10

3. ¿QUÉ ES EL LOG DE SALESFORCE? ............................................................................................................ 11

4. TIPOS DE LOGS .................................................................................................................................................... 12

5. NIVELES DE LOG .................................................................................................................................................. 15

6. EL LOG ESTÁ LIMITADO EN EL TIEMPO .................................................................................................. 21

7. EL LOG REQUIERE UN USUARIO................................................................................................................... 22

8. PARA TENER LOG HAY QUE TENER TRACE FLAG................................................................................. 24

9. LÍMITES Y SUS LIMITACIONES ................................................................................................................... 33

10. ¿DÓNDE Y CÓMO CONSULTAMOS EL LOG? ...................................................................................... 36

11. CÓMO LEER EL LOG PARA ENTENDERLO ............................................................................................ 51

12. CÓMO GENERAR ENTRADAS EN EL LOG .............................................................................................. 58

13. DATOS SENSIBLES AL GENERAR EL LOG ............................................................................................ 61

14. HERENCIA Y FILTERING DE LOGS .......................................................................................................... 68

15. CÓMO GESTIONAR LOGS CON LA API ................................................................................................ 74

16. CÓMO GESTIONAR LOGS CON LA SFDX CLI .................................................................................... 82

17. CASOS DE USO HABITUALES EN LOS PROYECTOS ....................................................................... 87

18. FRAMEWORKS DE LOGS .............................................................................................................................. 94

19. UN FRAMEWORK IDEAL ............................................................................................................................. 117

20. APÉNDICES ...................................................................................................................................................... 119

21. ENLACES Y CONTENIDOS INTERESANTES ....................................................................................... 123

22. AGRADECIMIENTOS .................................................................................................................................... 125

23. GARANTÍA........................................................................................................................................................ 126

24. CAMBIOS ENTRE VERSIONES ................................................................................................................. 127

4
Prólogo

1. Prólogo
1.1 ¿Por qué esta guía?
La respuesta es sencilla: porque me costaba entender y retener los conceptos para el uso del log
en Salesforce y porque en teoría no hay diferencia entre la práctica y la teoría. Pero en la práctica,
la hay.

Me frustré numerosas veces con la documentación dispersa de Salesforce, y no encontré una


única referencia para entender las capacidades, las limitaciones ni las recomendaciones de uso
del log.

Además, me di cuenta de que no era el único.

A medida que estudiaba, pensaba que sería muy útil que alguien lo explicara de una manera
distinta, siguiendo un orden de explicación distinto, explicando las implicaciones de las
limitaciones, proporcionando ejemplos y aclarando cómo responder a requerimientos que
aparecían recurrentemente en mis proyectos, y que no se podían satisfacer con la funcionalidad
estándar.

Con la búsqueda de soluciones encontré que otros usuarios se enfrentaban a las mismas
limitaciones y aportaban ideas muy interesantes, que podía aprovechar.

Y después de muchos meses, esta guía es mi propuesta para que lo que yo creí que podía ser útil
para mí, lo sea ahora para ti también.

En esta guía no invento nada, no creo un framework que revolucionará el ecosistema, ni propongo
soluciones mágicas. Lo que intento es proporcionarte toda la información útil, explicando los
componentes en el orden que creo que es correcto, de forma concisa, con ejemplos que puedas
usar de inmediato, y basados en casos de uso reales.

Mi objetivo es que esta guía te ayude a comprender qué es el log y cómo generarlo en distintas
herramientas, a conocer las limitaciones de antemano, a saber cómo afrontar y dar respuesta a los
requerimientos que aparezcan en tu proyecto, y a ser capaz de proponer soluciones robustas.

1.2 Antes que nada, ¿esta guía es para ti?


1.2.1 Si estás empezando
Si estás empezando en Salesforce, ¿debes conocer lo que se explica aquí? Rotundamente sí, sin
ninguna duda. De hecho, he escrito esta guía especialmente para ti.

No puedes esperar participar en un proyecto real sin conocer cómo usar el log de Salesforce, lo
siento. Sin saberlo andarás a ciegas al primer error o comportamiento que no esperes, y en ese
momento empezarás a bucear por diferentes documentos, páginas de blogs, etc., invirtiendo una
gran cantidad de tiempo, en un momento en que tienes prisa.

5
La guía definitiva para dominar el Log de Salesforce

Con esta guía, creo que conseguirás muy rápidamente aquello que necesitas, y consultar aquello
que aun no lo sabes, pero te será de ayuda, todo en un único lugar.

1.2.2 Si tienes experiencia como admin. / analista...


En mi opinión, todos los perfiles que participan en una implementación de Salesforce deben
conocer lo que se expone en la primera parte de esta guía. No creo que nadie pueda obviar cómo
obtener, analizar y comprender el log de Salesforce.

Si tienes experiencia previa, seguramente la parte de esta guía que está orientada a los conceptos
básicos ya te será familiar, pero casi con total seguridad, habrás visto todos los mecanismos de
consumo y gestión del log.

Si no tienes conocimientos de programación, la segunda parte de esta guía, referente a


frameworks, te costará un poco más. Aun así, quiero comentarte que estos apartados no intentan
ahondar en cómo están hechos estos frameworks, sino más bien qué ideas proponen, cómo
usarlos, qué resultados obtienes con cada uno de ellos y cuáles son sus ventajas e inconvenientes.

1.2.3 Si eres un programador experimentado


En tu caso, hazte estas preguntas:

• ¿Conozco la herencia y el Filtering de logs?

• ¿Tengo experiencia en SFDX para crear, generar y obtener el log?

• ¿Tengo experiencia en utilizar las APIs de Salesforce para generar y obtener el log de
Salesforce?

• ¿Tengo experiencia en frameworks de log para minimizar las limitaciones de Salesforce y


proponer un framework robusto?

Si has respondido “SÍ” a las preguntas anteriores creo que no deberías invertir tiempo en leer esta
guía; en caso contrario, muy probablemente te va a ser útil.

1.2.4 Cómo está organizada y cómo leer esta guía


Esta guía está organizada en 3 bloques claramente diferenciados, que te describo a continuación.

En el bloque 1:

• Es mi intención que entiendas qué es realmente el Log de Salesforce, y te introduciré los


conceptos del Log con la finalidad de crear tu propio Log, explicando los componentes que
van apareciendo en un orden que te será natural y así los interiorizarás fácilmente.

• En este mismo bloque, dedico un capítulo completo a los límites, que es crucial que
domines e interiorices. Sin conocerlos no es posible cometer los mismos errores que
muchos hemos cometido anteriormente.

6
Prólogo

• Habiendo generado tu propio log, te mostraré cómo leerlo en todas las herramientas
posibles, desde la Developer Console hasta API, CLI, etc., para que tengas todas las vías
identificadas, y recomiendes en cada situación la mejor herramienta.

• Más adelante te explicaré cómo está estructurado el log que se genera, cuáles son sus
partes, cómo leer cada línea de log y cómo sacar toda la información que se genera. Es
muy habitual encontrar usuarios que se quejan del contenido del log y se excesiva
verbosidad, pero creo que si entiendes su contenido, tu opinión no será la misma.

• Los últimos capítulos del bloque 1 explican cómo generar tus propias entradas en el log
mediante la famosa sentencia System.debug, donde creo que encontrarás capacidades e
implicaciones poco conocidas de esta sentencia.
Verás adicionalmente las técnicas de Herencia y Filtering de Logs, que son capacidades
que generan malentendidos entre aquellos que no las conocen y en cambio proporcionan
información muy concreta que necesitarás en ciertas ocasiones.

En el bloque 2:

• Este bloque está dedicado a cómo gestionar el log: cómo gestionar cada uno de sus
componentes, y así verás cómo crearlos, modificarlos y eliminarlos con la API y la SFDX
CLI.

• Dominando su gestión te propongo escenarios reales de automatización para usar estas


herramientas eficientemente, que creo te serán muy útiles cuando aparezcan en tu
proyecto o incluso tu puedas proponer proactivamente.

En el bloque 3:

• Analizo los frameworks de logs que están proponiendo los expertos, para aprovechar las
capacidades del log y aliviar sus limitaciones. Te explico, para cada uno, cuáles son sus
características y objetivos, cómo puedes usarlos y así evaluarlos tú mismo, y cuáles son, en
mi opinión, sus ventajas e inconvenientes. El objetivo de este capítulo es que aprendas lo
que están proponiendo los expertos, y puedas adaptar y proponer su adopción en tus
proyectos.

• Finalmente, dedico un capítulo a las características de un “framework ideal” (que es


enemigo de lo bueno) para que tengas un listado de todas las características que
considero imprescindibles/interesantes y que puedas elegir las que te encajan mejor en tu
proyecto (y que pueden variar entre proyectos).

Mi mejor recomendación es que leas la guía secuencialmente. Yo la escribo pensando que los
conceptos se van asentando correctamente en tu imaginario, e intento mantener un hilo
argumental coherente y ejemplificado.

En la parte referente a frameworks, te recomiendo una primera lectura secuencial, y


posteriormente ya podrás saltar de un framework. Es especialmente interesante que no obvies la

7
La guía definitiva para dominar el Log de Salesforce

introducción al uso de Platform Events, ya que así comprenderás la motivación de los nuevos
frameworks propuestos.

Creo que lo mejor que puedes hacer al leer este documento es practicar. He invertido muchas
horas en proporcionar ejemplos prácticos y que faciliten la comprensión; en la medida que
puedas, repítelos tú misma/o.

1.2.5 Acceder al repositorio de este libro


Todos los archivos, tanto de código como de imágenes y documentos, se encuentran
disponibles en este repositorio de Bitbucket: estevegraells / libro-la-guia-definitiva-para-
dominar-el-log-de-salesforce — Bitbucket1.

Si posees una versión impresa en blanco y negro, te aconsejo que visites este repositorio,
porque obtendrás imágenes en color de alta calidad, los ficheros de código y log completos.

1
https://bitbucket.org/estevegraells/libro-la-guia-definitiva-para-dominar-el-log-de-salesforce/src/master/

8
Prólogo

Bloque 1

9
La guía definitiva para dominar el Log de Salesforce

2. Un poco de contexto
Seguramente recordarás cuando Salesforce, como compañía y Marc Bernioff abanderaban el
slogan de No Software2, todo ha cambiado radicalmente desde entonces.

Desde 2013 Salesforce se ha consolidado como el proveedor CRM líder mundial3. Para ello
entre otras cosas ha abandonado el slogan inicial, y ha abrazado a la comunidad de
desarrollo en un esfuerzo continuado y a ritmo constante desde entonces.

Aún así debes tener en cuenta, que, aunque hoy en día estemos evaluando herramientas
como Code Builder, un entorno completo de desarrollo para Salesforce en la nube, muchos
desarrolladores utilizan a diario la vetusta y entrañable Developer Console, que en su día
revolucionó el desarrollo, con el mismo paradigma, desarrollar sin instalar herramientas.

Con esta vocación y desde este enfoque, es con el cual debemos situarnos ante todo lo que
iremos viendo en este libro.

Muchas de las características y limitaciones que veremos en el Log de Salesforce, requieren


de esta mirada histórica, cuando los administradores y los primeros desarrolladores de
Salesforce, utilizaban un entorno completamente en la nube, que era una innovación sin
referentes y un avance incomparable, pero que actualmente y sobretodo dada la evolución
de las plataformas de desarrollo cloud, acusa el paso del tiempo, pero que debes dominar.

2
Varias interpretaciones se ofrecen de este slogan, y algunas muy interesadas según mi opinión.
3
https://www.salesforce.com/news/press-releases/2020/05/22/salesforce-named-1-crm-provider-for-seventh-
consecutive-year-2/

10
¿Qué es el Log de Salesforce?

3. ¿Qué es el Log de Salesforce?


Vamos a empezar mal, pero a propósito, definiendo de forma muy distinta lo que es realmente el
Log de Salesforce:

El Log de Salesforce consiste en la definición y activación de un Trace Flag.

Sorprendido, ¿verdad? Si no te has enterado de nada, no hay ningún problema, déjame traducirlo a
otras palabras menos técnicas:

El Log de Salesforce consiste en obtener la información generada durante la ejecución de


ciertos eventos, durante un tiempo determinado.

Esta definición es más sencilla, pero desafortunadamente el uso del log de Salesforce requiere
que entiendas varios conceptos:

1. Tipos de log existentes en Salesforce

2. Qué eventos se generan en la plataforma

3. Categorías de eventos

4. Niveles de Log

5. Entidades traceables

6. Duración del Log (activo)

7. Qué es un Trace Flag

Antes de empezar, ten presente esto y evita confusiones: el Log y el Debug son cosas distintas. El
log se utiliza para el Debug de Salesforce, es decir, para debugar utilizamos el log generado, pero
antes hay que haberlo generado, y puedes generar log y no debugar.

Si tienes experiencia en usar sistemas Syslog o parecido, no desesperes. En la segunda parte de


este manual, verás cómo tener un sistema parecido, extendiendo la funcionalidad estándar.

11
La guía definitiva para dominar el Log de Salesforce

4. Tipos de Logs
Verás que se nombran 3 tipos de log en Salesforce:

Tipo Descripción y uso


Se crea de forma automática al abrir la Developer Console.
Tiene mucho sentido que, si estamos en la Developer Console
realizando acciones, obtengamos un log de forma automática sin
DEVELOPER_LOG
necesidad de crearlo.
Su vigencia se gestiona de forma automática y los puedes
modificar o eliminar.
Se crea manualmente para obtener la información de las
acciones de un usuario concreto. Este es el que utilizamos
USER_LOG
habitualmente para analizar incidencias concretas o evaluar el
funcionamiento de cierta funcionalidad.
Se crea manualmente para ampliar la información del log para
CLASS_TRACING ciertas clases o Triggers concretos. Su uso no es muy habitual,
pero lo veremos más adelante.

Seguramente, si tienes algo de experiencia, dirás: yo he visto nombrar también System Logs y los
Monitoring Logs, y tienes toda la razón, déjame que te lo traduzca:

Tipo A qué se refiere


Se refieren a los Logs generados del tipo DEVELOPER_LOG (ver
System Logs
la tabla anterior).
Se refieren a los logs generados manualmente (ver la tabla
Monitoring Logs
anterior).

4.1 Eventos
Volviendo a la definición, nos centramos en la primera parte:

El Log de Salesforce consiste en obtener la información generada durante la ejecución de


ciertos eventos, durante un tiempo determinado.

Pues, ¿cuáles son estos eventos? En la última actualización de esta guía, existen +200 eventos
de los que obtener información en el log, pero no tienes que memorizarlos, porque tampoco
podrás seleccionar individualmente cuáles quieres mostrar en tu log.

Cada uno de estos eventos pertenece a una de las categorías definidas por Salesforce
(consultables en el fichero Categorías y Eventos para un detalle completo).

Un ejemplo de evento es DML_BEGIN, que según la descripción oficial Debug Log Levels se
define como:

12
Tipos de Logs

Evento Descripción Categoría y Nivel


Muestra el número de línea, la
operación (como Insert o Pertenece a la categoría
DML_BEGIN Update), el nombre o tipo de Database y Aparece en el nivel
registro y el número de filas en INFO (y superiores)
la operación DML

Veamos a continuación qué son la categoría y el nivel.

4.2 Categorías de Eventos


Los eventos de los que obtenemos información en el log pertenecen a las siguientes categorías:

# Eventos
Categoría Descripción
asociados
Incluye eventos con información sobre la actividad de la
base de datos, incluyendo todos los datos del lenguaje de
Database 13
manipulación de datos (DML) y las declaraciones o
consultas en línea SOQL o SOSL.
Incluye eventos con información de reglas de flujos y
Workflow procesos, como el nombre de la regla y las acciones que se 94
ejecutarán.
Incluye eventos con información acerca de las reglas de
Validation validación, como el nombre de la regla y si la regla se 5
evaluará como verdadera o falsa.
Incluye eventos con el XML de solicitud de respuesta que
el servidor envía y recibe información de un servidor web
externo. Resulta útil cuando se depuran problemas
Callouts relacionados con el uso de llamadas de API del servicio 15
web de la plataforma Lightning o la solución de problemas
del acceso de usuarios a objetos externos a través de
Salesforce Connect.
Incluye eventos con información sobre el código de Apex.
Puede incluir información como mensajes de registros
generados por declaraciones DML, SOQL en línea o
Apex Code 47
consultas SOSL, el inicio y finalización de cualquier
desencadenador, así como la finalización de cualquier
método de prueba.
Incluye eventos con información sobre perfiles, como el
Apex Profiling 12
número de correos electrónicos enviados.
Incluye eventos con información de Visualforce como la
Visualforce 12
serialización y deserialización del estado de vista o la

13
La guía definitiva para dominar el Log de Salesforce

evaluación o un campo de fórmula en una página de


Visualforce.
Incluye eventos con información sobre llamadas a todos los
System 19
métodos de sistema como el método System.debug.
Incluye eventos con información acerca de la actividad de
Nba Einstein Next Best Action, como detalles de ejecución de 8
estrategia desde Strategy Builder.

Si quieres una lista detallada de todos los eventos, descarga el fichero Eventos Detallados y ábrelo
en tu navegador.

Por suerte no, no debes rastrear y seleccionar manualmente cuáles deseas en cada categoría, sino
que deberás seleccionar unas agrupaciones que ha realizado Salesforce denominadas Niveles de
Log.

Es decir, lo que acabarás seleccionando son qué Niveles de Log (agrupaciones de eventos en base
a su criticidad) deseas en cada categoría. Veamos cuáles son.

14
Niveles de Log

5. Niveles de Log
Los niveles de log son agrupaciones de eventos que Salesforce ha decidido juntar en función de la
criticidad (y no los puedes cambiar).

Los niveles están pensados en una estructura jerárquica, es decir, cada nivel contiene los eventos
del nivel anterior más los propios de ese nivel, y a esto lo llamamos la jerarquía de niveles.

En el siguiente diagrama te muestro la jerarquía completa de niveles existente. Como ves, cada
nivel incluye el anterior.

Ilustración 1 - Jerarquía de niveles de log

Es decir, como tenemos a los eventos agrupados en niveles, los eventos que estén en el nivel Error
forman parte del nivel Warn, y el nivel Warn incluye los eventos de None, los de Error y los
específicos de Warn.

Un mnemotécnico para recordar estos niveles que yo utilizo es juntar las iniciales formando: NEW-
ID-F3.

Hasta aquí toda la teoría que necesitas, hagamos un repaso:

• El log de Salesforce consiste en capturar la información generada por eventos.

• No puedes seleccionar individualmente entre los más de 200 eventos existentes, sino
que están agrupados por niveles de log.

• Los niveles de log son 8 (NEW-ID-F3) y están jerarquizados.

• Para cada categoría, debes seleccionar qué nivel de log deseas.

Veamos un ejemplo práctico de todo esto:

• Supongamos que quieres mostrar información en el log sobre cuándo se produce la


ejecución de un método (este evento es SYSTEMMETHODENTRY).

• Este evento pertenece a la categoría SYSTEM.

• En la categoría System, Salesforce ha implementado 4 niveles de log de los 8 posibles


(NONE, INFO, DEBUG y FINE).
15
La guía definitiva para dominar el Log de Salesforce

• El evento SYSTEMMETHODENTRY está en el nivel de log FINE.

• Por tanto, para obtener información sobre la ejecución de métodos deberás seleccionar el
nivel de log (esta expresión no es del todo correcta, pero me tomo una licencia) FINE para
la categoría SYSTEM.

En la tabla siguiente te muestro cómo Salesforce ha agrupado los 4 niveles de log para la
categoría SYSTEM.

Nivel de Eventos implementados en este nivel para la categoría SYSTEM


Log
NONE -
INFO 14 eventos:
SYSTEMMODEENTER; SYSTEMMODEEXIT;
DUPLICATEDETECTIONBEGIN; DUPLICATEDETECTIONRULEINVOCATION;
DUPLICATEDETECTIONMATCHINVOCATIONSUMMARY;
DUPLICATEDETECTIONEND; DUPLICATERULEFILTER;
DUPLICATERULEFILTERRESULT; DUPLICATERULEFILTERVALUE;
PUSHTRACEFLAGS; POPTRACEFLAGS; MATCHENGINEBEGIN;
MATCHENGINEINVOCATION; MATCHENGINE_END;
DEBUG 15 eventos: (los 14 del nivel INFO + 1 nuevo)
SYSTEMMODEENTER; SYSTEMMODEEXIT; DUPLICATEDETECTIONBEGIN;
DUPLICATEDETECTIONRULEINVOCATION;
DUPLICATEDETECTIONMATCHINVOCATIONSUMMARY;
DUPLICATEDETECTIONEND; DUPLICATERULEFILTER;
DUPLICATERULEFILTERRESULT; DUPLICATERULEFILTERVALUE;
PUSHTRACEFLAGS; POPTRACEFLAGS; MATCHENGINEBEGIN;
MATCHENGINEINVOCATION; MATCHENGINEEND;
DUPLICATEDETECTIONMATCHINVOCATION_DETAILS
FINE 19 eventos: (los 15 eventos del nivel DEBUG + 4 nuevos) SYSTEMMODEENTER;
SYSTEMMETHODEXIT; DUPLICATEDETECTIONBEGIN;
DUPLICATEDETECTIONRULEINVOCATION;
DUPLICATEDETECTIONMATCHINVOCATIONSUMMARY;
DUPLICATEDETECTIONEND; DUPLICATERULEFILTER;
DUPLICATERULEFILTERRESULT; DUPLICATERULEFILTERVALUE;
PUSHTRACEFLAGS; POPTRACEFLAGS; MATCHENGINEBEGIN;
MATCHENGINEINVOCATION; MATCHENGINEEND;
DUPLICATEDETECTIONMATCHINVOCATIONDETAILS;
SYSTEMMETHODENTRY; SYSTEMCONSTRUCTORENTRY;
SYSTEMCONSTRUCTOREXIT; SYSTEMMODE_EXIT;

Seguramente te estarás preguntando: yo solo quiero un evento, y ¿de golpe y porrazo mi log
mostrará información de 17 eventos? Es correcto, lo has entendido perfectamente, y empiezas a
ver las limitaciones/características del log.

16
Niveles de Log

Por lo tanto, si volvemos al ejemplo anterior de DML_BEGIN:

• Este evento se produce al iniciar la ejecución de una sentencia en la BD.

• Pertenece a la categoría DATABASE.

• Nivel de Log es INFO.

Información que proporciona el


Evento Categoría y Nivel
evento
Número de línea, operación (como
Insert o Update), nombre o tipo de
DML_BEGIN Database e INFO
registro y número de filas superadas
en la operación DML

Dado que el evento DML_BEGIN está incluido en el nivel INFO, también estará incluido en DEBUG y
FINEST.

Como habrás deducido, no todas las categorías implementan los 8 niveles, lo que hubiera sido
consistente, pero Salesforce ha decidido que, dependiendo de la categoría, esta implemente
ciertos niveles y otros no.

Esta es la tabla de los niveles definidos por Salesforce para cada categoría:

Categoría Niveles de log implementados por la categoría


Database NONE, INFO y FINEST
Workflow NONE, ERROR, WARN, INFO, FINE y FINER
Validation NONE e INFO
Callouts NONE, ERROR, INFO, FINE y FINER
Apex Code NONE, ERROR, WARN, INFO, FINE y FINER
Apex Profiling NONE, ERROR, WARN, INFO, DEBUG, FINE, FINER y FINEST
Visualforce NONE, INFO, FINE y FINER
System NONE, INFO, DEBUG y FINE
Nba NONE, ERROR y FINE

¿Ves algo curioso? A mí me llama la atención que no haya 2 categorías que implementen los
mismos niveles de log; todas implementan un conjunto de niveles distinto a las demás (es una
curiosidad).

En la documentación de Salesforce en castellano, creo que hay un error que puede inducir a
confusión, ya que indica "INFO y los anteriores" habiendo traducido del inglés "INFO and above".

Antes de seguir, si es necesario, vuelve a leer este apartado detenidamente.

17
La guía definitiva para dominar el Log de Salesforce

5.1 No te confundas, son niveles de Debug


Te advierto que entras en zona de confusión por los términos que utiliza Salesforce, sigue
conmigo.

Para tener un log activo, deberás seleccionar para cada una de las categorías un nivel de log
determinado, supongamos por ejemplo la siguiente selección:

1. Workflow -> NONE

2. Validation -> NONE

3. Callout -> NONE

4. Apex CODE -> FINER

5. Apex Profiling -> NONE

6. Visualforce -> FINER

7. System -> NONE

8. Database -> INFO

9. Nba -> NONE

Al observar esta combinación de categorías y niveles, vemos que está orientada a obtener
información de ejecución de código Apex, Visualforce y operaciones en la base de datos, nada
más.

Pues bien, cuando defines para cada categoría qué niveles deseas obtener, Salesforce lo
denomina técnicamente nivel de Debug (procedente de Debug Level en inglés).

Lo sé, ¿por qué utilizar nombres tan parecidos para el nivel de log de la categoría y para la
selección de todas las categorías llamándolo nivel de debug? Pero sigue conmigo, no te pierdas:

• Nivel de Log: es la agrupación de eventos que seleccionamos para cada categoría (donde
están agrupados los eventos).

• Nivel de Debug: es la combinación de todas las categorías con su nivel de log


seleccionado.

Veamos un listado de diferentes niveles de debug que he creado en el sistema:

18
Niveles de Log

Ilustración 2 - Ejemplo de listado de niveles de debug

• El nivel de debug que he creado, llamado NBA_INFO, fija todas las categorías con un nivel
de log a NONE, excepto NBA, con un nivel de log con valor INFO.

• El nivel de debug NoneLogs es inusual porque lo he definido para no obtener ninguna


información, por lo tanto, todas las categorías tienen un nivel de log con valor NONE.

• El nivel de debug SFDC_DevConsole es algo distinto y peculiar, a la vez que muy conocido,
porque no lo he creado yo, sino que lo crea el sistema.

Si entramos en detalle en el nivel de debug denominado SFDC_DevConsole, puedes ver los


eventos que forman parte de la selección.

Ilustración 3 - Definición del nivel de debug SFDC_DevConsole

¿Recuerdas que cuando vimos los tipos de log te comentaba que existía uno que se activaba
automáticamente al utilizar la Developer Console? Voilà!

19
La guía definitiva para dominar el Log de Salesforce

Pues ahora ya podemos hablar con total propiedad: al abrir la Developer Console, la plataforma
activa un Trace Flan cuyo nivel de debug se denomina SFDC_DevConsole.

Vale, hagamos una parada aquí, porque acabo de introducir un nuevo término, el Trace Flag, no te
preocupes, veremos qué es de inmediato.

Pero antes, debo presentarte 2 de las limitaciones más importantes del log de Salesforce, por las
que la mayoría de los usuarios expresan su descontento.

En esta guía observarás que muchas veces utilizo el término en inglés Debug Level en lugar de
nivel de debug. Prefiero esta nomenclatura porque permite diferenciar los términos de nivel de log
y nivel de debug, que son demasiado parecidos.

20
El log está limitado en el tiempo

6. El log está limitado en el tiempo


Volviendo a la definición, nos centramos ahora en la segunda parte:

El Log de Salesforce consiste en obtener la información generada durante la ejecución de


ciertos eventos, durante un tiempo determinado.

Sí, así es, el log solo se ejecuta durante un tiempo determinado, y además:

1. El período de duración máximo activo es de 24 horas (si quieres más, deberás


automatizarlo; veremos en el apartado como usar la API para conseguirlo).

2. El período se fija mediante 2 valores:

1. Start Date: puede ser vacía, indicando que lo queremos desde Ahora o en el futuro
para retrasar su inicio.

2. Expiration Date: fecha hasta la que estará activo el Trace Flag.

Por lo tanto, recuerda como regla de oro: el log no está siempre activo, tiene una vigencia y no
puede superar las 24 horas.

21
La guía definitiva para dominar el Log de Salesforce

7. El log requiere un usuario


Volviendo a la definición:

El Log de Salesforce consiste en obtener la información generada durante la ejecución de


ciertos eventos, durante un tiempo determinado.

Pero tengo que añadirte: para una entidad determinada (usuario, clase Apex o Trigger...)

Esta es seguramente una de las partes más confusas y peor entendidas, especialmente si tienes
experiencia en el uso de log en otros lenguajes de programación.

Como ya sabes, no tendrás un log continuamente activo, sino únicamente durante un período de
tiempo y sólo para determinadas entidades.

Aquí la palabra entidad es ambigua, y te recomiendo que la sustituyas por el concepto "para qué
usuario" se muestra el Log.

Por tanto, acabamos de adecuar la definición y completarla:

El Log de Salesforce consiste en obtener la información generada durante la ejecución de


ciertos eventos, durante un tiempo determinado sobre ciertas entidades (usuario).

Abordemos inicialmente el "sobre ciertas entidades". Existen estas posibilidades:

1. Se registrará información de eventos en el Log cuando se produzcan eventos provocados por


un usuario determinado (es la más habitual, por eso lo incluyo en la definición).

2. Se registrará información de eventos en el Log cuando se produzcan eventos provocados por


el Automated Process User.

3. Se registrará información de eventos en el Log cuando se produzcan eventos provocados por


el Platform Integration User.

Y, existiendo un log activo para un usuario:

1. Puedes sobrescribir los niveles de log para una clase Apex concreta.

2. Puedes sobrescribir los niveles de log para un Trigger concreto.

Por lo tanto, acabas de ver otra de las limitaciones más importantes de la plataforma: el log debe
estar siempre asociado a un usuario.

Estas 2 limitaciones (vigencia y asociación a un usuario concreto) requieren que determines qué
quieres analizar, durante qué período y para quién.

Seguramente estarás pensando “Cuando un usuario de mi proyecto tenga una incidencia, digamos
en el entorno de PRO, difícilmente tendré un log activo para este usuario en este entorno”. Y no te
falta razón.

22
El log requiere un usuario

Esto es un gran inconveniente y un gran cambio si tienes experiencia en otras plataformas, donde
el log no está limitado a un usuario ni a un tiempo de vigencia, y en mi opinión es una de las
grandes debilidades del log, ya que difícilmente permite investigar lo que ha pasado, sino que una
vez ha sucedido algo, tengo que identificar cómo reproducirlo (pidiendo al usuario que describa lo
que estaba haciendo, lo que seguramente no será muy fiable si ni se acuerda) y activar un log para
reproducirla e iniciar la investigación.

Pero ya estamos llegando al final del camino para tener un log activo en la plataforma. Veamos
finalmente qué es el concepto de Trace Flag.

23
La guía definitiva para dominar el Log de Salesforce

8. Para tener Log hay que tener Trace Flag


Cuando al principio de esta guía empecé mal, a propósito, te dije:

El Log de Salesforce consiste en la definición y ejecución de un Trace Flag.

El Trace Flag es el mecanismo que conjuga todos los conceptos anteriores para tener un log
activo que registre la información que queremos obtener, y consiste en definir las siguientes
entidades:

1. Seleccionar la entidad traceable (usuario, clase Apex o Trigger).


2. Seleccionar un nivel de debug (existente o creado por nosotros).
3. Seleccionar el período de vigencia.

8.1 Cómo crear un Trace Flag


El proceso para crear un Trace Flag es muy sencillo. Accede a Setup -> Environments -> Logs ->
Debug Logs:

En el apartado de User Trace Flags, selecciona New:

Ilustración 4 - No hay debug logs definidos por defecto

Selecciona:

1. El tipo de entidad traceable.

2. El período de vigencia.

3. El nivel de debug.

24
Para tener Log hay que tener Trace Flag

Ilustración 5 - Pantalla de definición de un Trace Flag

Seguramente te estás preguntando “¿Cuándo defino el nivel de debug?” Para ello, tan solo tienes
que seleccionar New Debug Level:

Ilustración 6 - Donde definir/indicar el nivel de debug para el Trace Flag que se está creando

Y te aparecerá la ventana de creación de un nuevo nivel de debug:

• Deberás asignarle un nombre único (y simple: alfanumérico, sin espacios, que empiece por
letras).

• Para cada categoría deberás seleccionar el nivel de log que deseas. Al seleccionar esta
opción se añadirán o eliminarán eventos que se irán mostrando, para que valides que
tendrás la información de los eventos que deseas.

25
La guía definitiva para dominar el Log de Salesforce

Ilustración 7 - Definición de los niveles de log para cada categoría del nivel de Debug

A continuación, te muestro el resultado de haber creado un Trace Flag:

• (Para quién) Para el usuario Frodo Bolson.

• (Qué obtener) Con un nivel de debug denominado SoloApexFine.

• (Período) Desde el 21/10/2020 a las 11.35 hasta las 12.05.

Ilustración 8 - Listado de Trace Flags existentes en el sistema

El nivel de debug SoloApexFine contiene por lo tanto los siguientes eventos:

Ilustración 9 - Definición del nivel de debug SoloApexFine


26
Para tener Log hay que tener Trace Flag

Este mismo proceso puede realizarse desde la Developer Console. Accede al menú de Debug ->
Change Log Levels.

Ilustración 10 - Modificar los Trace Flags a través de la Developer Console

Aparece la ventana de creación, que es un poco distinta porque está dividida en 3 áreas:

1. Área superior: es Trace Flag activo por defecto que utiliza el nivel de Debug SFDC_DevConsole
por defecto de Salesforce.

2. Área inferior: donde definimos Trace Flags para usuarios concretos (debemos conocer el ID).

3. Área intermedia: donde definimos Trace Flags para clases Apex y Triggers.

Ilustración 11 - Listado de Trace Flags a través de la Developer Console

A diferencia de lo que vemos en la UI de Salesforce, los colores indican si ese Trace Flag está
activo o caducado, lo que es útil para evitar confusiones.

8.2 Creación de Trace Flags para clases Apex y


Triggers
Si recuerdas el concepto de entidades traceables, te comenté que existían 3: un usuario, una clase
Apex o un Trigger. Hasta ahora solo hemos visto la creación de un Trace Flag para un usuario, pero
¿deberías usar las otras 2? Esto puede ser muy útil en el siguiente escenario:

• Un usuario tiene activo un Trace Flag que genera la información que hemos considerado
necesaria.
27
La guía definitiva para dominar el Log de Salesforce

• Dada una incidencia concreta con este usuario, queremos ampliar el log para ciertas clases
Apex o Triggers en los que puede estar la incidencia.

Desafortunadamente, siendo esta capacidad muy útil, lleva a confusión por la manera en que se
define. A continuación, te enumero sus peculiaridades:

• Un Trace Flag para una clase o un Trigger no genera información de log si no existe un
Trace Flag activo y vigente para un usuario concreto.

• Un Trace Flag para una clase o un Trigger sobrescribe la definición del Trace Flag del
usuario. Existe una excepción al punto anterior que me encontré en un proyecto: si defines
un Trace Flag para un usuario con el nivel de log None en todas sus categorías, aunque
definas un Trace Flag para una clase o un Trigger este no prevalecerá y no se generará log.

• Solo puede existir un Trace Flag vigente para una clase o un Trigger.

• Los Trace Flags definidos para clases o Triggers no aparecen en la pantalla de Debug Logs
de la plataforma, sino que debes acceder a las pantallas de Apex Triggers o Apex Classes
del Setup y consultar la columna denominada Has Trace Flags.

Ilustración 12 - Listado de triggers con el indicador de Trace Flag

La definición de un Trace Flag para una clase o un Trigger es exactamente análoga que para un
usuario. En la siguiente captura, he seleccionado:

• Tipo de entidad traceable: Apex Trigger.

• Nombre del Trigger: MyCustomObjectTrigger (que es un trigger que he creado previamente).

• Período de vigencia: durante 30' a partir del 21/10/2020 a las 14.24.

• He asignado el nivel de debug SoloApexFine que te mostré anteriormente.

28
Para tener Log hay que tener Trace Flag

Ilustración 13 - Definición de un Trace Flag para un Trigger

Por cierto, en esta pantalla me encuentro habitualmente un bug, cuando una vez seleccionado el
Trigger o la clase Apex, aparece un error indicando que la clase o el Trigger no existen, pero sé
positivamente que existen. Para seleccionarlo, repite la misma acción y entonces sí lo acepta
(quien la persigue la consigue).

Existe otra manera de definir este mismo Trace Flag: accede a los Triggers de la plataforma (Setup
-> Custom Code -> Apex Triggers) y en el apartado Trace Flags, selecciona el New.

Ilustración 14 - Pestaña de Trace Flag al ver el contenido de un Trigger

A continuación, puedes ver la captura de cómo aparece un Trace Flag:

Ilustración 15 - Listado de Trace Flags de un Trigger

29
La guía definitiva para dominar el Log de Salesforce

Llegados a este punto hagamos un resumen mediante esta tabla para afianzar los diferentes
escenarios que hemos visto:

¿Existe un Trace Flag ¿Existe un Trace Flag


(TF) vigente para un (TF) definido para Log obtenido
usuario? Trigger/Clase?
No Sí No se genera Log
Sí, todas las categorías
tienen un nivel de log = Sí No se genera Log
NONE
Se genera el log correspondiente al
Sí No
Trace Flag del usuario
Se genera el log correspondiente al
Sí Sí
Trace Flag del Trigger o clase Apex

8.3 ¿Existe un Trace Flag por defecto?


Esta es una pregunta común que te puedes hacer al trabajar con el log.

• Primero: no existe un Trace Flag siempre activo, te lo demuestro:

Ilustración 16 - No existe un Trace Flag por defecto

• Segundo: sin embargo, existe un Trace Flag por defecto que se activa en ciertas
situaciones, que ya comenté anteriormente. Estas situaciones son:

1. Al abrir la Developer Console.

2. Al ejecutar Tests (si no hay Trace Flags activos anteriormente).

Las llamadas API que no tienen Log activado mediante cabeceras no generan logs (aunque la
documentación indica que generan unos logs Transient, yo no los he encontrado, ni aparecen en la
UI, ni en la Developer Console ni quedan registrados en el objeto ApexLog).

Habiendo matizado este punto, veamos las características de este Trace Flag:

• Su tipo es DEVELOPER_LOG.

• Su nivel de debug es SFDC_DevConsole (¿recuerdas que lo vimos anteriormente?).

30
Para tener Log hay que tener Trace Flag

• Su vigencia se renueva automáticamente.

Ilustración 17 - Trace Flag SFDC_DevConsole

A continuación, te comento ciertas situaciones peculiares que me he encontrado que te pueden


ser útiles:

1. No veo el log generado en la pantalla de Debug Logs, ¿es un error? No, esto es debido a que
los logs de Developer_LOG solo son visibles en la Developer Console o también accesibles vía
API o CLI (lo veremos más adelante).

• ¿Puedes cambiar este Debug Level? Sí, aunque la plataforma lo crea


automáticamente no impide modificarlo.

2. Quiero eliminar el Trace Flag creado por la Developer Console, ¿es posible? Sí, pero cuando
vuelvas a abrirla no se recrea el Trace Flag hasta al cabo de 5', y durante ese período no
tendrás log.

3. Quiero cambiar el usuario de Trace Flag de tipo DEVELOPER_LOG, ¿es posible? Sí, pero los
logs que se generen solo serán visibles en la Developer Console, vía CLI o consultando el
objeto ApexLog.

8.4 Generar logs en llamadas API


Para observar qué sucede en las invocaciones que hacemos mediante llamadas API, no hay
ningún mecanismo especial ni característica adicional.

Habitualmente nuestras invocaciones acabarán ejecutando métodos de nuestras clases, donde


aplicarán los mismos mecanismos de gestión del log comentados hasta el momento.

Aun así, puede suceder que queramos ampliar el contenido del log puntualmente. Para ello es
habitual seguir el siguiente esquema:

1. Invocar la API para crear un Trace Flag concreto para el usuario de integración que realizará
las llamadas API.

2. Ejecutar la llamada API que queremos observar.

3. Eliminar el Trace Flag creado, para evitar seguir generando log, ya que, si el volumen de
ejecuciones de integración es elevado, este log aumentará rápidamente de tamaño.

4. Descargar el log generado.

5. Opcionalmente, eliminar el log una vez descargado.

31
La guía definitiva para dominar el Log de Salesforce

En el caso particular que estemos invocando servicios mediante SOAP, existe la posibilidad de
simplificar todo esto mediante el uso de la cabecera DebuggingHeader.

Esta cabecera permite especificar ciertos niveles de Log que se tendrán en cuenta únicamente
para la llamada en concreto. Este mecanismo permite evitar tener que ejecutar el proceso de 5
pasos. El log generado fruto del uso de la cabecera DebuggingHeader se recibe en una cabecera
denominada DebuggingInfo.

Desafortunadamente, puede suceder que el uso de DebuggingHeader no produzca el efecto


esperado, dado que se produce una colisión con otro Trace Flag existente, el cual toma
precedencia.

Puedes obtener más información sobre esta funcionalidad en la documentación oficial: Debugging
Apex API Calls, Receive Debug Logs Predictably4.

4
https://salesforce.stackexchange.com/questions/77645/does-the-summer-15-release-remove-the-ability-to-set-
test-logging-levels-with-t

32
Límites y sus limitaciones

9. Límites y sus limitaciones


Seguramente este es el apartado que más te puede ayudar a evitar situaciones inesperadas que
frustren tu trabajo diario con el log.

No solo te muestro los límites que están disponibles en la documentación de Salesforce, sino
también las limitaciones que se derivan en un proyecto habitual y los retos a los que te
enfrentarás.

9.1 Límites de la plataforma


Hagamos un recordatorio de los límites de la plataforma, que puedes encontrar en la
documentación oficial de Log Limits.5

1. El log está activo por un máximo de 24 horas.

2. El log que hayas generado se mantiene por 7 días.

3. Si generas más de 1.000 MB de logs en 15 minutos, la plataforma desactivará los Trace flags y
no los podrás activar hasta al cabo de 15 minutos.

4. Si acumulas 1.000 MB para todos los logs generados, no se pueden crear o modificar los Trace
Flags.

5. Si el tamaño del log generado es superior a 20 MB, la plataforma trunca en cachitos de 200
KB empezando por las entradas más longevas y que no podrás recuperar.

9.2 Limitaciones importantes del Log


De los límites anteriores seguramente deduces ciertas limitaciones que condicionarán tu
desempeño con el log.

A continuación, veamos un listado completo de las limitaciones y cómo te verás afectado:

1. Dado que la duración máxima de un log activo es de 24h, si en tu proyecto se solicita


mantener el log siempre activo, deberás proporcionar mecanismos adicionales para obtenerlo.

2. Dado que el log debe ser activado para un usuario, no es posible realizarlo por perfil, por
objeto, o mediante condiciones que puedas requerir. Si en tu proyecto solicitan tener el log
activo para un determinado proceso independientemente de qué usuario lo lleve a cabo,
deberás proporcionar mecanismos adicionales para obtenerlo.

3. Debes tener cuidado con el tamaño del log que generes y debes proporcionar un proceso de
limpieza de logs si crees que vas a superar los límites antes de 7 días (lo que es habitual
cuando varios equipos trabajan conjuntamente):

5
https://help.salesforce.com/articleView?id=sf.code_debug_log.htm&type=5

33
La guía definitiva para dominar el Log de Salesforce

1. Si generas un log superior a 20 MB, perderás parte del log.

2. Si el log que generáis tú y tus compañeros se acumula hasta superar los 1.000 MB, no
podréis modificar ni crear Trace Flags.

4. El log no permite consultas con SOQL, y por consiguiente tampoco es susceptible de ser
utilizado mediante Reports. Si en tu proyecto se solicita un informe para consultar los errores
aparecidos en el log, deberás proporcionar mecanismos adicionales.

5. El formato del log siempre es textual en formato fichero, lo que implica que:

• Si el log es suficientemente grande, la plataforma genera varios ficheros


descargables, que deberás fusionar para hacer búsquedas en una única fuente.

• Si en tu proyecto/cliente se utilizan herramientas o plataformas para centralizar los


logs, deberás proporcionar código adicional para descargar y enviar estos ficheros a
estas plataformas; no existe un mecanismo estándar para reenviarlo.

• Deberás valorar con cuidado los escenarios anteriores, ya que el contenido del log
puede ser truncado de forma automática para evitar sobrepasar el límite (20 MB).

6. En cualquier proyecto es común que el equipo de administración y/o seguridad solicite que, si
ocurren ciertos errores o aparecen ciertos mensajes en el log, se lo notifiques mediante un
correo o invocación de una API (concepto de trap). Para satisfacer este requerimiento deberás
proporcionar código adicional (Spoiler: en los frameworks que te comento en esta guía, alguno
de los autores lo ha tenido en cuenta).

7. En entornos regulados como GxP para la industria farmacéutica, o entornos certificados en


banca, o con datos sensibles en cualquier industria, el log no es sensible al entorno en que se
ejecuta. Por tanto, deberás proporcionar código adicional, para detectar en qué (tipo de)
entorno estás (sandbox o PRO) y filtrar el contenido del log para evitar volcar datos sensibles.

8. Respecto al punto anterior, recuerda que no puedes volcar cualquier dato que necesites, ya
que en la mayoría de las legislaciones existe el requerimiento de respetar la sensibilidad de
los datos de las personas y de las entidades.
Pero el log no conoce la sensibilidad de los datos: al volcar los datos de un objeto, todos sus
miembros son mostrados, independientemente de si alguno de ellos no debería mostrarse por
ser altamente sensible (como en el punto anterior, esto puede suponer un problema de acceso
a datos sensibles y un accidente de seguridad de datos, intenta evitarlo).

9. Aunque puede ser obvio, el log no está disponible para flujos de Process Builder, con lo que no
es posible tener un registro unificado de una transacción que requiera de ejecución de flujos y
de código Apex, lo que es un caso bastante habitual (nuevamente te hago spoiler: verás el
ejemplo de un framework donde se explica cómo llevarlo a cabo).

10. El log no captura información de los Managed Packages que puedas estar utilizando, a menos
que sean de tu propiedad.

11. El log no se ejecuta durante la instalación de un Package, con lo que si existen errores en esa
fase no puedes confiar en el Log.
34
Límites y sus limitaciones

La visualización del log es comúnmente tachada de espartana (en los próximos capítulos te
mostraré todas las opciones disponibles para obtenerlo). Personalmente estoy de acuerdo, aunque
esto no difiere excesivamente de otras plataformas donde he trabajado, aunque repito que
Salesforce podría mejorarlo sensiblemente.

Finalmente quiero comentarte que en algunos proyectos me solicitaron utilizar la plataforma de


logs que usaba la empresa y que había externalizado. Muchas empresas centralizan sus logs en
plataformas externas donde analizarlos como Loggly6 o la familia de Elastic Search7, pero hay
muchos otros. En esta situación deberás proporcionar un mecanismo fuera del estándar, y analizar
correctamente:

• La periodicidad del volcado de esos logs a la plataforma externa, evitando la limitación de


7 días.

• Proporcionar un mecanismo de limpieza de los logs que ya has enviado para evitar superar
el límite de 1.000 MB.

• Asegurar que tus logs individuales no superen los 20 MB para evitar el truncado individual.

9.3 Instrumentación compleja con el log


Quizás aun no has pensado en ello, pero no existe el concepto de log para diagnóstico de errores
y otro tipo de log para saber cómo se está comportando la plataforma, lo que algunos
especialistas llaman instrumentación de la plataforma.

La instrumentación permite obtener y analizar datos del comportamiento del uso de la plataforma,
siendo aplicable a todos los usuarios, y no perece inmediatamente, sino que usa para comparar
cambios de comportamiento históricos, encontrar patrones de uso desconocidos, etc.

Es complejo instrumentalizar mediante el log de Salesforce, dadas sus características (usuario


determinado, vigencia, limitación del almacenamiento, etc.), pero en la segunda parte de esta guía
verás cómo algunos autores proponen soluciones a estas limitaciones mediante frameworks.

Finalmente debes saber que Salesforce proporciona una solución bajo suscripción con coste
adicional denominada Event Monitoring8, que forma parte de Salesforce Shield. Esta funcionalidad
permite monitorizar en tiempo real ciertos eventos y aumentar el nivel de auditoría.

6
https://www.loggly.com/
7
https://www.elastic.co/what-is/kibana
8
file:///Users/egraells/.Trash/salesforce event monitoring logs
35
La guía definitiva para dominar el Log de Salesforce

10. ¿Dónde y cómo consultamos el Log?


Existen diversas maneras de acceder al log:

1. En la interfaz de usuario de la plataforma.

2. En la Developer Console.

3. Mediante invocaciones a la SFDX CLI.

4. Mediante la consulta del objeto ApexLog en la base de datos mediante SOQL e invocación de
APIs.

5. En el editor Visual Studio Code.

6. En Workbench.

Veamos cada una de ellas.

10.1 Consulta de logs en la interfaz de usuario


Recuerda que al principio de esta guía vimos que se podían generar 2 tipos de log: USERLOG y
DEVELOPERLOG. Ambos los podrás encontrar en la misma ubicación del Setup -> Debug Logs:

Ilustración 18 - Listado de logs generados

Curiosamente la columna de Status se muestra en el idioma que tenga configurado el usuario del
Trace Flag, no del usuario que consulta los logs.

En esta interfaz puedes realizar las siguientes acciones:

1. Ver el contenido de un log determinado: lo ves en pantalla, nada en especial.

36
¿Dónde y cómo consultamos el Log?

2. Descargarlo: esta opción es útil por ejemplo en la situación que no tienes acceso al entorno de
PRO, y necesitas pedirle al administrador que te envíe un log determinado.

3. Eliminar logs.

10.2 Consulta en la Developer Console


En la Developer Console es posible ver los logs, pero debes evitar confusiones, porque su
visualización depende de las opciones que tengas seleccionadas en los menús.

Ilustración 19 - Listado de Logs en la Developer Console

Mediante la opción de Filter, en la parte inferior, filtras lo que quieres ver, teniendo en cuenta que
este filtro se aplica a las columnas Application, Operation, Status y Time (algunos valores
solamente).

Las opciones del Menu Debug son las que van a condicionar cómo ves estos logs:

1. Auto-Hide Logs: si refrescas la pantalla, los logs no vuelven a aparecer (a mí no me parece muy
útil justamente, pero... ).

2. Show My Current Logs Only: esta es la opción que provoca más confusiones y aparece por
defecto activada. Es decir, por defecto, solo verás los logs generados por el usuario que haya
abierto la Developer Console. Si quieres ver todos los logs, deberás desmarcarlo, como
aparece en la captura siguiente.

3. Clear + Log Panel: limpia la tabla de logs y los dejas de ver; si quieres volver a verlos, vuelve a
marcar la opción de Show My Current Logs Only.

37
La guía definitiva para dominar el Log de Salesforce

Ilustración 20 – Opciones de configuración para mostrar logs en la Developer Console

Por cierto, la columna Read indica si ese log ya lo has visualizado, y no que se haya realizado una
consulta, como me enseñó un compañero (al principio incluso dudé que fuera cierto).

Presta atención a la siguiente opción en el menú de preferencias de la Console:

Ilustración 21 - Opción Prevents Logs on Load en la Developer Console

También puedes personalizar las columnas que se muestran en el log, como por ejemplo mostrar
el ID del log (este ID te será útil para descargarlo o visualizarlo vía API o consulta SOQL).

Ilustración 22 - Personalización de columnas en la Developer Console

Para ver el contenido de un log, en su línea haz click con el botón derecho y aparecen las
siguientes opciones (como puedes ver en la pantalla siguiente):

1. Open Log: muestra el log en una tabla con columnas para filtrar, analizar, buscar, etc.

2. Open Raw Log: muestra el Log en formato textual, que permite copiar y pegar en un correo.

38
¿Dónde y cómo consultamos el Log?

3. Download Log: descargas ese mismo Log pero en un fichero en tu ordenador.

Ilustración 23 - Opciones disponibles para un log concreto

Al seleccionar la opción de Open Log, aparece la siguiente pantalla (o al menos parecida, dado
que yo he activado la visualización de más columnas:

Ilustración 24 - Ejemplo de contenido de un log

Como te comentaba, se pueden personalizar las columnas, pero desafortunadamente lo deberás


repetir cada vez.

Ilustración 25 - Columnas disponibles para la visualización de un log

En esta pantalla existen 4 opciones para filtrar las líneas de Log:

• This Frame: permite delimitar un ámbito, si quieres mostrar únicamente la parte


correspondiente a las acciones entre CODEUNITSTARTED y CODEUNITENDED. A mí
personalmente esta función no me ayuda y no la utilizo casi nunca.

39
La guía definitiva para dominar el Log de Salesforce

• Executable: permite únicamente mostrar las líneas de log que se refieren a acciones
llevadas a cabo, y elimina otras líneas como LIMIT_USAGE*, que proporcionan información
sobre límites, etc.

• Debug Only: la más usada de todas las opciones, permite mostrar las líneas de log que se
han incluido mediante la sentencia System.Debug.

• Filter: permite filtrar por el texto que introduzcas tanto en la columna Event como Details.

Verás que solo he comentado la pantalla correspondiente al Execution Log, pero existen 6
pantallas más, que complementan las herramientas de Debug de Salesforce. Requeriría un libro
entero describir las capacidades completas de esas herramientas, y creo que consultando la
documentación que hay disponible es suficiente para entenderlo.

Ilustración 26 - Paneles disponibles en la Developer Console

Echo de menos 2 funcionalidades, y seguramente tú también:

1. No es posible descargar el Execution Log en formato CSV para analizarlo.

2. No es posible descargar varios logs simultáneamente (que con la opción anterior me permitiría
descargar todos los logs y analizarlos en Excel).

10.3 Consulta mediante la SFDX CLI


Seguramente conocerás la SFDX CLI9: es la herramienta proporcionada por Salesforce para
acceder a distintas funcionalidades mediante la línea de comandos. Puedes encontrar más
información y cómo instalarla en este enlace Documentación oficial de estos comandos10.

Si no estás familiarizado con la SFDX CLI, te recomiendo que dediques un poco de tiempo a
hacerlo, porque con las capacidades de automatización que te aportará, podrás dar respuesta a
requerimientos que difícilmente podrás repetir manualmente para el tratamiento de logs.

Además, muchas de las funcionalidades que está preparando Salesforce, como el nuevo Code
Builder11 (está actualmente en fase piloto para unos pocos clientes) y el hecho de que esté

9
https://developer.salesforce.com/tools/sfdxcli
10
https://developer.salesforce.com/docs/atlas.en-
us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_force_apex.htm?search_text=log#cli_reference_force_a
pex_log_list
11
https://developer.salesforce.com/blogs/2020/06/introducing-code-builder.html

40
¿Dónde y cómo consultamos el Log?

fundamentado en Salesforce CLI debe animarte a sumergirte en las capacidades de esta


herramienta.

Vamos a realizar un repaso de todos los comandos disponibles para consultar el log, con
ejemplos prácticos, y a analizar sus capacidades principales:

• Mediante force:apex:log:list: listar todos los logs generados del sistema tanto en
formato de texto plano como en formato Json (interesante si pretendes integrar esta
operación con otros comandos o herramientas).
Ejemplos:

• sfdx force:apex:log:list: lista todos los logs

Ejemplo comando sfdx force:apex:log:list


• sfdx force:apex:log:list --loglevel DEBUG:lista aquellos logs pertenecientes a un
tipo concreto: TRACE, DEBUG, INFO, WARN, ERROR, FATAL.

• force:apex:log:tail: muestra el log en nuestra consola de terminal a medida que se va


generando, estando limitado a 30'. Tiene ciertas particularidades:

• Si no hay un Trace Flag activo de tipo DEVELOPER_LOG, lo crea automáticamente,


aunque podemos especificar el Trace Flag que deseamos (e incluso crearlo, veremos
cómo justo a continuación).

• Permite obtener el log en color para ciertas variables utilizando (--color). Incluso
permitía definir tus propios colores (desafortunadamente a mí ya no me funciona ni
en Linux ni en Windows, y según me respondieron del soporte de Salesforce, es un
bug conocido para algunos usuarios).

• Permite aplicar una pipe a la salida obtenida del log. Esto permite, tal y como comenta
Andrew Fawcett en este artículo, mostrar solo aquellos mensajes que tienen ciertas
cadenas de texto. En la captura de pantalla siguiente, puedes ver cómo estoy filtrando para
obtener las cadenas que tienen "USER_".

Ilustración 27 - Obtención del log en el terminal con una pipe aplicada

41
La guía definitiva para dominar el Log de Salesforce

• Para Windows Powershell puedes usar esta sentencia equivalente: sfdx


force:apex:log:tail | Select-String -Pattern USER_ (gracias a este artículo de Antonin
Januska12).

Log Terminal con Grep en Powershell


• force:apex:log:get: descarga los logs existentes.

• Puedes obtener los logs en formato Json.

• Puedes obtener los n últimos logs, o los logs por ID (idealmente los obtendrás
mediante el comando anterior force:apex:log:list) y los puedes descargar a una
ubicación concreta. En el siguiente ejemplo solicito la descarga del log con ID =
07L09000000DAEGEA4:

Ilustración 28 - Ejemplo de ejecución del comando force:apex:log:list


• Con estas capacidades puedes automatizar la descarga de logs y almacenarlos en
formato estructurado; ¿recuerdas que era uno de los casos de uso que nos
planteábamos anteriormente?

• sfdx force:data:record:get: mediante los comandos force:data podemos consultar los


datos identificativos de un log, excepto descargar su contenido: sfdx
force:data:record:get -s ApexLog -i 07L09000000DAEGEA4

12
https://antjanus.com/blog/web-development-tutorials/how-to-grep-in-powershell/

42
¿Dónde y cómo consultamos el Log?

Ilustración 29 - Ejemplo de ejecución del comando force:data:record:get

10.4 Consulta mediante SOQL y APIs


También es posible consultar los logs mediante consultas SOQL e invocaciones a las APIs
estándar de Salesforce. En la siguiente tabla resumo estas capacidades y las comparo:

¿Accesible vía SOQL //


Capacidad ¿Accesible vía Tooling API?
API REST Query?
Obtener el listado de los logs Sí, vía query al objeto
Sí, vía query al objeto ApexLog
existentes ApexLog
Obtener los datos de Sí, vía query al objeto
Sí, vía el sobject ApexLog
cabecera de un log ApexLog
Obtener el contenido de un
No Sí, vía el sobject ApexLog
log

Por lo tanto, para la consulta de logs tenemos 2 alternativas:

• Usar SOQL o REST API, que nos permite listar los logs existentes y obtener las
propiedades de un log concreto.

• Usar la Tooling API para:

• Listar los logs existentes y obtener las propiedades de un log concreto y acceder a
sus características y descargar el contenido.

• Borrar Logs existentes (ya generados).

• Gestionar los Debug Levels accediendo al sobject DebugLevel.

• Gestionar (crear, borrar y modificar) los Trace Flags.

Veamos a continuación cómo usar SOQL y cómo usar la API.

43
La guía definitiva para dominar el Log de Salesforce

10.4.1 Mediante SOQL


Como hemos visto, mediante SOQL puedes listar los logs existentes. La clave está en el uso del
objeto ApexLog.

Por ejemplo, con la consulta SELECT Application, DurationMilliseconds, Id, LastModifiedDate,


Location, LogLength, LogUserId, Operation, Request, RequestIdentifier, StartTime, Status
FROM ApexLog, obtendrás mucha de la información disponible de los logs existentes.

Ilustración 30 - Resultado de la consulta para obtener el detalle de los logs existentes

En la lista de campos no aparece Body, dado que no puedes acceder al contenido. Finalmente,
para acceder a un log concreto adapta la consulta anterior filtrando sobre el campo ID o cualquier
otro que requieras.

10.4.2 Mediante API REST


Con la API REST puedes realizar exactamente las mismas consultas invocando el recurso /query
de la API.

Análogamente, pues, con


/services/data/v50.0/query/?q=SELECT+Application,DurationMilliseconds,Id,LastModifiedDat
e,Location,LogLength,LogUserId,Operation,Request,RequestIdentifier,StartTime,Status+FROM
+ApexLog, obtenemos el listado de los logs con sus atributos:

44
¿Dónde y cómo consultamos el Log?

Ilustración 31 - Resultado de la consulta mediante API


para obtener el detalle de los logs

Por cierto, la respuesta contiene además el atributo url para acceder directamente al contenido
(Body) del log.

Para descargarlo, ejecuta la siguiente llamada:


/services/data/v{{version}}/query/?q=SELECT+Id,LogUserID,StartTime+FROM+ApexLog+WHERE+Id
='07L09000000DDMUEA4'

Ilustración 32 - Resultado de ejecutar una consulta para obtener el detalle de un log

Para realizar estas invocaciones, verás que he utilizado la aplicación Postman, que me parece tan
buena como Paw, SoapUI, Postwoman, etc. Al final de este libro, encontrarás un apéndice de por

45
La guía definitiva para dominar el Log de Salesforce

qué uso Postman y cómo aprovechar los materiales que Salesforce ha generado para esta
herramienta.

Por lo tanto, vía SOQL y API REST podemos consultar los logs generados, pero no mucho más.
Para gestionar completamente los logs del sistema, disponemos de la Tooling API. Veamos qué
capacidades nos proporciona.

10.4.3 Mediante Tooling API


Como seguramente recuerdas, la Tooling API tiene varios endpoints, que te muestro en la
siguiente captura, destacando 2 (también los encontrarás en la colección de todas las APIs de
Salesforce con Postman13):

• /services/data/v{{version}}/tooling/query?q: permite realizar consultas sobre todos los


objetos con la query especificada en el parámetro q

• /services/data/v{{version}}/tooling/sobjects/<SOBJECT_API_NAME>: permite acceder a


un objeto como ApexLog

Ilustración 33 - Invocaciones para Tooling API

Veamos cómo utilizarlas para obtener todos los logs generados en el sistema. La siguiente
invocación obtiene todas las entradas del objeto ApexLog realizando una consulta:

{{_endpoint}}/services/data/v{{version}}/tooling/query/?q=SELECT+Id+FROM+apexlog

13
https://github.com/forcedotcom/postman-salesforce-apis

46
¿Dónde y cómo consultamos el Log?

Ilustración 34 - Obtención de listado de logs mediante invocación a la Tooling API

Para acceder a la cabecera de un log concreto, especificamos su ID:

Ilustración 35 - Obtener la cabecera de un log mediante invocación a la Tooling API

Pero ahora, además, podemos obtener el contenido body, mediante el recurso


/sobjects/ApexLog/id/Body/ especificando en el parámetro ID el identificador del log que
deseamos descargar:

47
La guía definitiva para dominar el Log de Salesforce

Ilustración 36 - Obtención del contenido de un log mediante invocación a la API

10.5 Consulta mediante Visual Studio Code


Ahora que ya sabes que los logs pueden obtenerse con la CLI, SOQL y las APIs, es ideal que veas
cómo obtener los logs en el editor Visual Studio Code y con las extensiones de Salesforce14
instaladas.

El comando para obtener los logs es: SFDX: Get Apex Debug Logs...

Ilustración 37 - Comando de VSCode para obtener los logs existentes

Al ejecutar esta acción, seleccionamos el log a descargar (desafortunadamente no es posible


descargarlos todos).

14
https://trailhead.salesforce.com/en/content/learn/projects/quickstart-vscode-salesforce

48
¿Dónde y cómo consultamos el Log?

Ilustración 38 - Selección del log a descargar en VSCode

Al descargar estos logs quedan almacenados en la carpeta .sfdx/tools/debug/logs de tu


proyecto:

Ilustración 39 - Ubicación de los logs descargados

10.6 Consulta mediante Workbench


Existe la posibilidad de ver el log de una ejecución de código anónimo en Workbench. Para
acceder al log desde Workbench existen 2 posibilidades:

• En la pantalla de Settings, al final de la página:

Ilustración 40 - Opciones para obtener log en Workbench


• En la misma pantalla de ejecución:

49
La guía definitiva para dominar el Log de Salesforce

Ilustración 41 - Obtención de log en Workbench tras ejecutar sentencias

50
Cómo leer el Log para entenderlo

11. Cómo leer el Log para entenderlo


Estarás sorprendido de que no sea hasta ahora cuando veamos cómo leer el contenido de un log,
pero, si lo hubiera hecho antes, creo que hubiéramos pasado por alto varios conceptos
importantes.

Un log está compuesto por las siguientes partes:

1. Cabecera

2. Execution Units

3. Code Units

4. Líneas de Log

5. Información sobre los recursos del sistema que se han utilizado

En este diagrama te muestro cómo está organizado el log, aunque no siempre aparecen todas las
partes:

Ilustración 42 - Contenido jerárquico del Log

Veamos un ejemplo real para entender cómo se muestran estas partes y qué contenido albergan
(he eliminado algunas líneas pertenecientes a eventos que ahora no son relevantes).

En el siguiente esquema, cada color indica una parte distinta del log, siguiendo el diagrama
anterior, y así puedes establecer la correlación fácilmente. Si tienes una versión impresa de
esta guía te recomiendo que visites los siguientes enlaces para obtener las imágenes a todo
color: https://bitbucket.org/estevegraells/libro-la-guia-definitiva-para-dominar-el-log-de-
salesforce/src/master/Images/PartesLogEsquema.png y
https://bitbucket.org/estevegraells/libro-la-guia-definitiva-para-dominar-el-log-de-
salesforce/src/master/Images/PartesLogEsquema2.png.

51
La guía definitiva para dominar el Log de Salesforce

52
Cómo leer el Log para entenderlo

Veamos a continuación cada una de las partes que han aparecido.

11.1 Cabecera
En la cabecera aparecen:

• La versión de la API utilizada.

• La información de la configuración del Trace Flag, con cada categoría y su nivel de log
asignado.

50.0 APEX_CODE,FINEST; APEX_PROFILING,INFO; CALLOUT,INFO; DB,FINEST; NBA,INFO;


SYSTEM,DEBUG; VALIDATION,INFO; VISUALFORCE,INFO; WAVE,INFO; WORKFLOW,INFO

Si hubiéramos ejecutado un código Apex anónimo, además se informa de:

• El contenido del código APEX enviado.

• Información de la ORG, del usuario que lo ejecutó y de su zona horaria.

Execute Anonymous: Account a = new Account (Name='New Line Cinema');


Execute Anonymous: insert a;
Execute Anonymous:

53
La guía definitiva para dominar el Log de Salesforce

Execute Anonymous: MyCustomObject__c myCustom = new MyCustomObject__c (Name='Test1324');


Execute Anonymous: insert myCustom;
18:31:55.1
(1697403)|USER_INFO|[EXTERNAL]|00509000000dfmQ|estevemain@logs.com|(GMT+01:00) Central
European Standard Time (Europe/Paris)|GMT+01:00

11.2 Execution Unit


Una Execution Unit es el concepto utilizado para denominar transacción, es un contenedor de
Code Units y tiene las siguientes características:

• Está delimitada por las cadenas EXECUTION STARTED y EXECUTION FINISHED.

• Dentro de la Execution Unit aparecen una o varias Code Unit Executions.

11.3 Code Unit


Code Unit es el concepto utilizado para denominar unidad de trabajo, un concepto algo vago. En la
siguiente lista, puedes ver cuáles son las ejecuciones que provocan la creación de una Code Unit;
no es una lista exhaustiva, pero sí incluye las que creo más relevantes:

• Triggers

• La invocación de un proceso o flujo (Process Builder, Flow Builder)

• La invocación de un time-based workflow

• Validation rules

• Approval processes

• Apex lead convert

• La invocación de un método @future

• La invocación de un Web Service

• Un código Apex Anónimo

• El inicio de la ejecución de una clase con la interface Batchable: para los métodos start y
finish y para cada ejecución del método execute

• La ejecución del método execute de una Apex System.Schedule

Una Code Unit tiene las siguientes características:

• Está delimitada por las cadenas CODE_UNIT STARTED y CODE_UNIT FINISHED.

• Dentro de cada Code Unit pueden aparecer otras Code Units embedidas.

11.4 Línea de log


Cada línea de log está formada por 2 partes diferenciadas:

54
Cómo leer el Log para entenderlo

Ilustración 43 - Estructura de una línea de log

11.4.1 Cómo leer el instante


El instante está formado por 2 elementos:

• HH:mm:ss.SSS: momento en que sucedió este evento en el horario de la zona del usuario.
En el ejemplo: 18:31:55.1.

• (nanosegundos): los transcurridos desde el inicio de la transacción. Este dato no aparece


en la Developer Console, pero puede verse cuando se selecciona el formato Raw Log (o al
descargarlo vía API). En el ejemplo: (9333058).

La parte correspondiente a los detalles depende del evento que haya sucedido. Veamos a
continuación varios ejemplos de detalles para diferentes eventos.

11.4.2 Cómo leer los detalles


A continuación, te muestro las líneas de log que considero más interesantes y habituales en el día
a día para cada ejemplo y cómo leerlos correctamente.

11.4.3 Ejemplo 1: inicialización de variable


VARIABLE_SCOPE_BEGIN|[6]|acc|Account|true|false:

• Se ha producido un evento de inicialización de variable | En la línea del código: 6 | Variable


usada: acción | Tipo del objeto involucrado: Account | ¿Esta variable puede ser
referenciada? Sí | ¿Esta variable es estática? No

• Dado que la variable puede ser referenciada, no es estática y se trata de una Account, del
evento VARIABLESCOPEBEGIN, nos vemos ante la asignación de la variable acc.

• Si volvemos al código, en la línea 6 nos encontramos con este código: for (Account acc :
Trigger.new) {, que justamente indica la asignación sobre la variable acc.

11.4.4 Ejemplo 2: ejecución System.Debug


USER_DEBUG|[3]|DEBUG|-ege- Estoy en el Trigger de Account:

• Se ha generado una entrada por petición del usuario | En la línea de código: 3 | Nivel de
Debug: Debug | Texto proporcionado por el usuario: -ege- ...

• Esta es la típica ejecución de la sentencia System.Debug(), que veremos más adelante, en


la que el usuario genera una entrada en el log.

55
La guía definitiva para dominar el Log de Salesforce

• Si volvemos al código, en la línea 6 encontramos: System.Debug('-ege- Estoy en el


Trigger de Account');

11.4.5 Ejemplo 3: asignación a una variable


VARIABLE_ASSIGNMENT|[8]|this.Name|"La Comarca"|0x17736214:

• Se ha producido una asignación a una variable | Línea del código: 8 | Variable usada:
this.Name | Valor usado: "La Comarca" | La dirección de la variable (que a mí
personalmente no me dice casi nada)

• Si volvemos al código, en la línea 8 encontramos: acc.Name = 'La Comarca';

11.4.6 Ejemplo 4: inicio ejecución


EXECUTION_STARTED

• Este evento no tiene información adicional.

11.4.7 Ejemplo 5: inicio de un Trigger


CODE_UNIT_STARTED|[EXTERNAL]|TRIGGERS

• Inicio de una Unit Code | No se puede localizar un número de línea explicito, por eso se
indica [EXTERNAL] | Estamos en un Trigger.

• Estamos al inicio de la ejecución de un Trigger.

11.4.8 Ejemplo 6: se ha utilizado el Heap


HEAP_ALLOCATE|[79]|Bytes:3

• Se han consumido bytes del heap | Se produce en la línea 79 del código | Se consumen 3
bytes.

11.4.9 Ejemplo 7: se inicia la ejecución de un método


METHOD_ENTRY|[1]|01p09000004IEJr|AddressChanger.AddressChanger()

• Se inicia un método | En la línea del código: 1 | Identificador de la clase en la plataforma |


Namespace y nombre del método

• En este caso nos encontramos ante la ejecución del constructor de la clase; el namespace
y el nombre del método coinciden.

11.4.10 Ejemplo 8: resumen del consumo de los límites


LIMIT_USAGE_FOR_NS Default | (default)

• Al finalizar una Code Unit se muestra un listado de los recursos del sistema utilizados.

56
Cómo leer el Log para entenderlo

• El namespace donde se han utilizado los recursos, que con el valor default se refiere al
namespace de la Org por defecto, es decir, si hubiera otros packages con namespaces
distintos, aparecerían los recursos consumidos.

• Cabe destacar que los Managed Packages tienen sus propios límites separados de la Org,
y por lo tanto, mostrarán el nombre del namespace al final de este evento en lugar de
default.

• Si utilizas un Unmanaged Package consumirá los recursos de la Org, aunque puede


aparecer con un namespace propio (existen ciertas condiciones en las cuales al usarse un
unmanaged package aparezca su propio namespace pero consumiendo los límites de la
Org).

Como he anunciado, podemos generar nuestras propias entradas mediante la famosa sentencia
System.Debug. Veamos cómo usarla.

57
La guía definitiva para dominar el Log de Salesforce

12. Cómo generar entradas en el log


Para generar nuestras propias entradas en el log, disponemos de 2 métodos estáticos, ambos
pertenecientes a la clase System:

• System.debug (Obj msg)

• System.debug (System.LoggingLevel level, Obj msg)

Lo he escrito de una manera algo diferente, ya que quiero resaltar ciertos aspectos.

Aunque lo más habitual es encontrarnos con código que solo vuelca cadenas de texto al estilo
System.debug('Estoy en la función HelloWorld'), realmente no estamos limitados a
proporcionar únicamente un String, sino que la firma de estos métodos estáticos esperan un
objeto.

Si este objeto no es un String, existen 2 posibilidades:

• Objeto estándar: se mostrarán todos los valores del objeto hasta una longitud máxima del
string.

• Objeto custom: se invocará el método String.valueOf, que invocará toString() de la clase


a la que pertenece el objeto.

Por lo tanto, si estamos tratando con un objeto custom, podemos implementar este método y así
generar la información que deseemos en el log para este objeto.

Te comento esto porque si recuerdas mi preocupación por evitar mostrar datos sensibles, puedes
paliarlo conociendo cómo se muestran los datos de un objeto custom, no así para un objeto
estándar.

Veamos ejemplos a continuación.

12.1 Uso de System.debug


Veamos un ejemplo del uso de System.Debug que comentamos justo al finalizar el apartado
anterior:

• La clase AddressChanger contiene únicamente un método estático; por lo tanto, si


invocamos el siguiente código:

AddressChanger addressChanger = new AddressChanger();


System.debug(AddressChanger);

obtenemos el siguiente log:

17:14:25.0 (10634780)|USER_DEBUG|[14]|DEBUG|AddressChanger:[]

• Ahora implementemos en esta misma clase el método toString tal y como aparece a
continuación:

58
Cómo generar entradas en el log

public with sharing class AddressChanger {

public static void setAddress(Account acc){


System.Debug('-ege- Estoy en la clase AddressChanger');
acc.BillingCountry = 'Tierra Media';
DescriptionChanger.setDescription(acc);
}

public override String toString (){


return 'Este es el objeto: AddressChanger invocado desde ' + getTipoLlamada();
}

private String getTipoLlamada(){


switch on Request.getCurrent().getQuiddity(){
when Anonymous {
return 'Apex Anónimo';
}
when SYNCHRONOUS {
return 'Llamada síncrona';
}
when else {
return 'Otro tipo de llamada';
}
}
}
}

y obtenemos el siguiente Log:

17:40:41.1 (14205034)|USER_DEBUG|[14]|DEBUG|Este es el objeto: AddressChanger


invocado desde Llamada síncrona

Como ves, mediante la implementación de toString mostramos la información que nos


interesa en el formato que deseamos, y además en este caso accedo al contexto de la
llamada y así también informo de cómo se invocó.

12.2 Uso de System.Debug con nivel de debug


Es habitual incluir mensajes en el log en función de su criticidad.

Para ello utilizamos el segundo método: System.debug(System.LoggingLevel level, Obj msg),


sabiendo que System.LoggingLevel es un enum con los siguientes valores: NONE, ERROR, WARN,
INFO, DEBUG, FINE, FINER, FINEST.

Cuando especificamos el LoggingLevel indicamos para qué nivel máximo de log queremos
mostrar nuestros mensajes en el log (recuerda que los niveles de Log son incrementales).

Así, si durante la ejecución de nuestro código, existe un Trace Flag activo con el Debug Level WARN
asignado a la categoría Apex Code e invocamos el método con un LoggingLevel con valor
LoggingLevel.INFO, este se mostrará en el Log, y no aparecerá si el LoggingLevel es
LoggingLevel.ERROR .

Veamos un ejemplo con código donde existe un Trace Flag activo como el siguiente:

59
La guía definitiva para dominar el Log de Salesforce

Ilustración 44 - Descripción del nivel de debug APEX_CODE_WARN

Si modificamos el código de la siguiente manera:

AddressChanger addressChanger = new AddressChanger();


System.debug(LoggingLevel.ERROR, AddressChanger);

el log que obtendremos es:

18:23:27.2 (5793164)|USER_DEBUG|[14]|ERROR|Este es el objeto: AddressChanger invocado


desde Llamada síncrona

pero si ejecutamos el código:

AddressChanger addressChanger = new AddressChanger();


System.debug(LoggingLevel.INFO, AddressChanger); //he modificado el LoggingLevel
a INFO

no aparecerá ninguna entrada en el log, con lo que hemos conseguido filtrar mensajes que no
queríamos ver.

Si recuerdas el diagrama, verás que si nuestro Trace Flag está fijado en un nivel de log de Warn, se
mostrarán todos los mensajes de log marcados con los niveles Error y Warn, pero no los
superiores.

Ilustración 45 - Niveles de Log

60
Datos sensibles al generar el Log

13. Datos sensibles al generar el Log


Lo sé, soy muy pesado con este tema15, pero vuelvo a dedicar unas líneas a un tema concreto que
he experimentado en mis propias carnes y que se repite al trabajar en entornos regulados o
altamente sensibles con los datos usados.

Cuando trabajas en un entorno con datos sensibles (GDPR, etc.) es muy importante que consideres
los datos que vas a volcar en el log, ya que serán visible para todos aquellos que tengan acceso a
él, tanto vía interfaz de usuario, como vía API, CLI, etc.

Puede parecer obvio lo que comento, pero déjame darte un poco de perspectiva:

• España es el país comunitario que más multas pone por infracción de GDPR16 por un
valor de 15,5 millones de € en 2020.

• Una sanción puede suponer hasta 20 millones de € o hasta el 4% de la facturación


de una empresa.

• Estas sanciones se imponen si se ha vulnerado los derechos de los usuarios, si no se


ha recabado el consentimiento o si se han transferido los datos personales a una
entidad en un tercer país u organización internacional.17

• En un informe presentado a 900 profesionales de TI, las principales amenazas en


seguridad informática: errores de administración, intercambio de datos
confidenciales, mala configuración de la nube y robo de datos.18

Así, situémonos en nuestro contexto habitual:

• Los empleados somos una de las principales amenazas para la confidencialidad de


los datos.

• El mercado laboral de Salesforce está en constante crecimiento, con una comunidad


creciente. En todos los proyectos, se incorporarán nuevos compañeros que quizás no
tendrán la experiencia ni los conocimientos para no caer en la sensación de incluir
en el log datos sensibles.

• En proyectos con cierta envergadura, conviven varios equipos, quizás de empresas


distintas, seguramente en varios países distintos, en husos horarios con pocas horas
comunes con rotaciones de personal, a veces elevadas. Estos equipos construyen
varios aplicativos que se ejecutan en la misma Org. Por ello, afrontan regularmente
operaciones de Merge de metadata y código, en las cuales, irremediablemente

15
Debes saber que mucha de la culpa del detalle de este capítulo proviene por las muy acertadas
recomendaciones que me dio David Sánchez durante su revisión de este libro.
16
https://www.xataka.com/pro/2020-se-pusieron-multas-gdpr-que-nunca-tambien-altas
17
https://egida.es/sanciones-rgpd/
18
https://www.redeszone.net/noticias/seguridad/ataques-internos-externos-red/

61
La guía definitiva para dominar el Log de Salesforce

existirán sentencias de Log, que ayudarán a diagnosticar posibles situaciones, pero


que nadie valida respecto a la sensibilidad de los datos.

En esta situación creo que es imprescindible adoptar todas las medidas posibles para minimizar
incidentes de seguridad, y por ello, te propongo las siguientes recomendaciones y una propuesta
de procedimiento para paliar en gran medida este riesgo.

13.1 Recomendaciones para el equipo de desarrollo


A continuación, te propongo que el equipo de desarrollo de tu proyecto adopte las siguientes
recomendaciones, y se incluyan como documentación en vuestro Developer Handbook, Manual de
Buenas Prácticas o documento similar con las guías que habéis establecido para realizar vuestro
desarrollo.

1. Si estás volcando información de un objeto en el log, debe limitarse exclusivamente a


los campos concretos necesarios; no volcar todo el contenido del registro completo,
que es lo que muchos hacemos.

2. Si es necesario volcar datos son sensibles, antes valora estas opciones:

1. ¿Sería suficiente saber si el valor del campo contiene alguna información o


está vacío?

2. ¿Sería suficiente si únicamente obtengo la longitud del valor del campo?

3. ¿Sería suficiente mostrar los últimos caracteres del campo sin mostrarlo todo?

4. ¿Sería suficiente generar un hash del valor para así poderlo comparar con
algún otro valor?

3. Si las propuestas anteriores no son factibles, propón al Compliance Manager 19 la


posibilidad del volcado encriptado.
La cadena secreta, la clave privada o el certificado que utilices para encriptar, será
custodiada/acordada por el departamento de Compliance. La información volcada en
el log será la mínima posible, encriptada y nunca podrá ser relacionada con un cliente.
Para ello, te sugiero que utilices la clase Crypto20 que ofrece Salesforce, y te aconsejo
leer algún artículo con ejemplos como el que ofrece Nick Huber en este artículo21.

4. Una vez generado el log, debe eliminarse de inmediato, limitando el tiempo de


exposición a otros usuarios de la plataforma.
Recuerda, que existen situaciones, dónde puede pasarte inadvertida la generación del

19
No traduzco esta palabra, porque en mucha documentación y habitualmente es el término que creo determina
mejor esta área de trabajo.
20
https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_classes_restful_crypto.htm
21
https://salesforcenick.com/2019/08/07/using-the-apex-crypto-class-with-examples/

62
Datos sensibles al generar el Log

log, como por ejemplo, al validar los datos recibidos mediante una integración, ya que
no puedes controlar quién va a ejecutarla durante ese período, quién podrá verlo, etc.

Llegados a este punto, te confieso que hecho en falta un procedimiento robusto, que todos los
compañeros del equipo podamos seguir. Por ello déjame proponerte uno, que es posible gracias a
una funcionalidad estándar de Salesforce, denominada Data Classification Metadata (Campos de
Metadatos de clasificación de datos).22

13.2 Una propuesta de procedimiento para


minimizar el log de datos sensibles con DCM
La funcionalidad de Data Classification Metadata (en adelante DCM), permite indicar para
cada campo, quien es el propietario del dato, el nivel de sensibilidad del valor almacenado, y
clasificarlo en función de unos niveles de Compliance que establecemos en cada proyecto y
empresa.

Esta información es accesible tanto mediante Reports, como vía API o vía código APEX.

Veamos un ejemplo: en la siguiente captura de pantalla puedes ver como he creado un


campo DNI-NIE en el objeto Account, donde he informado:

1. El propietario del campo soy yo mismo (aquí estoy actuando con el Rol de
Compliance Manager o Data Manager).

2. He seleccionado que el campo está siendo utilizado (Active).

3. El nivel de sensibilidad es un valor utilizado en las empresas farmacéuticas para


indicar este valor como sensible (GxP).

4. Y finalmente indico que este campo está sujeto a GDPR.

Ilustración 46 - Ejemplo de información de datos para DCM

22
https://help.salesforce.com/articleView?id=sf.data_classification_metadata_fields.htm&type=5

63
La guía definitiva para dominar el Log de Salesforce

Puede ser que los valores existentes en las picklists estándar de DCM no se ajusten a la
industria o regulación del país. Para ello, es posible modificar los valores de estas listas,
accediendo a Setup -> Data Classification Settings.

Ilustración 47 - Configuración de DCM

En la siguiente captura puedes ver como he añadido el campo que te he comentado


previamente, típico de la industria farmacéutica:

Ilustración 48 - Ejemplo de modificación de la lista de Sensibilidad de datos en DCM

Esta funcionalidad no proporciona ninguna otra capacidad adicional, no encripta los datos
como lo realiza Shield, no realiza enmascaramiento de los datos, o ninguna otra parecida,
pero es totalmente útil para establecer el siguiente proceso.

13.2.1 Proceso de uso de DCM con el Log


Este proceso es el que te propongo que adaptes en tu equipo de desarrollo:

1. Configurar el módulo de DCM, modificando las listas de valores de sensibilidad y


categorización, acordadas con el Data Manager y el Compliance Manager del proyecto.

2. Crea un Report Type que sea un Join de los objetos Entity Definitions y Field Definitions.
Es importante que modifiques el Layout para añadir los campos correspondientes al

64
Datos sensibles al generar el Log

DCM que están en el objeto Field Definitions (te adjunto 2 capturas de pantalla a
continuación).

3. Realiza una carga de datos inicial de todos los campos, mediante la opción de Setup->
Data Classification Upload. Si no realizas esta carga, todos los campos están sin
categorizar.

4. Para cada nuevo campo que deba crearse en un objeto, deben establecerse los valores
de DCM: propietario, sensibilidad y categorización.
No debes obviar los campos fórmula, aunque deriven de otros.

5. Al final de cada Sprint genera el informe (como el que te muestro a continuación) y


envíalo al Compliance Manager para su validación. Alternativamente podrías descargar
un fichero CSV mediante la opción Setup->Data Classification Download, pero tiene
ciertas limitaciones, por lo que no te lo recomiendo.

6. Este mismo informe difúndelo entre todos los desarrolladores, para que eviten
introducir estos campos en el Log mediante su código.

Ilustración 49 - Creación de un Report Type para generar informes sobre DCM

65
La guía definitiva para dominar el Log de Salesforce

Ilustración 50 - Recuerda modificar el Layout para incluir los campos de DCM

Ilustración 51 - Ejemplo de informe, donde aparece el campo DNI que había informado
previamente

Con todo lo que hemos visto hasta ahora, la pregunta que queda sobre la mesa es: teniendo
DCM configurado y actualizado en nuestro proyecto, ¿puedo minimizar los incidentes? Y
afortunadamente, la respuesta es SÍ.

En el último bloque de este libro te explicaré como usar frameworks de logs para generar log
de manera ordenada, práctica y eficiente.

Verás que algunos de estos frameworks proporcionan la capacidad de filtrar ciertos literales,
campos, etc, para evitar incluir en el log patrones que no deseamos.

Dado que la información de DCM es consultable vía código APEX, es posible aplicar la
misma idea, para filtrar los campos cuya sensibilidad sea inadecuada para volcarse en el
Log. De esta manera, aunque un programador incluya una sentencia, podremos decidir si
mostrarla o no en función del entorno y sensibilidad, así, por ejemplo, el campo DNI en un
entorno de pruebas con datos ficticios, puede mostrarse sin reparo, aunque el mismo campo
en un entorno de Producción no debe ser mostrado.

66
Datos sensibles al generar el Log

Ya te adelanto que desafortunadamente, ninguno de los frameworks que te explico en este


libro, ni ningún otro que yo conozca, utiliza esta técnica de filtrado, con lo que ¿podrías ser
que tú el primero en implementarlo en tu proyecto y compartirlo en la comunidad?

67
La guía definitiva para dominar el Log de Salesforce

14. Herencia y Filtering de logs


14.1 En qué consiste la herencia de logs
Existe una funcionalidad del sistema de logs de Salesforce que provoca malentendidos y varias
entradas en los fórums quejándose de un log inesperadamente voluminoso.

Veremos a continuación que esto no es un mal funcionamiento de la plataforma, sino que es


debido a un mal entendimiento de lo que podemos denominar la herencia del log.

Analicemos el siguiente escenario: sobre una clase Apex o un Trigger definimos un trace flag de
tipo CLASS_TRACING.

• Si recuerdas el apartado Entidades Traceables, vimos que definir un Trace Flag sobre una
clase Apex o un Trigger realmente significa “sobrescribir” los niveles de un trace flag
activo de un usuario.

• Es decir, si existe un trace flag activo para un usuario en el momento de la ejecución de la


clase o el Trigger, se sobrescriben los niveles establecidos en el trace flag por los de la
clase Apex o el Trigger.

Pues a partir de este momento aparece la herencia de logs: todas las clases que se ejecuten en
el contexto de ejecución heredan el nivel de log que se haya sobrescrito en la clase inicial.

Seguramente puedes ver la consecuencia que provoca esta herencia: el usuario que ha creado el
trace flag sobre la clase espera ver en el log únicamente la información procedente de la clase o el
Trigger concreto, pero descubre que el log generado contiene mucha más información; de hecho,
se sorprende al obtener un log de todas las clases involucradas en la transacción.

Veamos a continuación un ejemplo completo con toda la configuración y el código asociado.

14.1.1 Herencia en acción


Veamos un escenario completo de herencia de logs:

1. Supongamos que creamos un Trigger sobre el objeto Account que modifica los valores de la/s
Account/s recibida/s.

2. Para llevar a cabo estos cambios en Account, este Trigger invoca una clase auxiliar que
modifica únicamente un campo de la Account, y a su vez esta clase realiza la invocación a otra
clase auxiliar, donde se modifican otros campos.

3. Y finalmente supongamos que hemos configurado un Trace Flag sobre un usuario que creará
una o varias Accounts, cuando este Trace Flag está activo.

Hasta el momento no existían incidencias sobre esta funcionalidad, pero hoy nos han informado
de que se ha encontrado un posible error durante el proceso, y te piden que lo investigues.

68
Herencia y Filtering de logs

Por ello, configuras un trace flag sobre el Trigger para que proporcione información adicional que
no está aportando el actual trace flag del usuario, ya que intuyes que el problema está en el código
del Trigger.

A continuación, vemos toda esta configuración de trace flags, y el código del Trigger junto a las 2
clases:

• El Trace Flag del usuario vigente utiliza un Debug Level denominado TODO_NONE:

Ilustración 52 - Trace flag activo TODO_NONE

TODO_NONE se ha definido como:

APEX_CODE,NONE;APEX_PROFILING,NONE;CALLOUT,NONE;DB,NONE;NBA,ERROR;SYSTEM,NONE;VALIDATION
,NONE;VISUALFORCE,NONE;WAVE,NONE;WORKFLOW,NONE

El Trace Flag del Trigger utiliza el Debug Level denominado LOG_COMPLETO:

Ilustración 53 - Trace flag activo sobre Trigger

LOG_COMPLETO se ha definido como:

APEX_CODE,FINEST;APEX_PROFILING,FINEST;CALLOUT,FINEST;DB,FINEST;NBA,FINE;SYSTEM,FINE;VAL
IDATION,INFO;VISUALFORCE,FINER;WAVE,FINEST;WORKFLOW,FINER

Y el código del Trigger y las 2 clases son los siguientes:


trigger AccountTrigger on Account (before insert) {
System.Debug('-ege- Estoy en el Trigger de Account');
for (Account acc : Trigger.new) {
acc.Name = 'La Comarca';
AddressChanger.setAddress(acc); //Invoca a la clase AddressChanger
}
}

public with sharing class AddressChanger {


public static void setAddress(Account acc){
System.Debug('-ege- Estoy en la clase AddressChanger');
acc.BillingCountry = 'Tierra Media';
DescriptionChanger.setDescription(acc); // Invoca a la clase DescriptionChanger
}
}

public with sharing class DescriptionChanger {


public static void setDescription(Account acc){
System.Debug('-ege- Estoy en la clase DescriptionChanger');
69
La guía definitiva para dominar el Log de Salesforce

acc.Description = 'La Comarca forma parte del legendarium creado por Tolkien'; //Modifica
otro atributo
}
}

Al ejecutar el Trigger, el log es sumamente largo: ocupa 146 líneas (no sé si esperabas tantas
líneas; puedes descargarlo entero aquí: Log con Herencia23). Veamos los motivos y qué está
sucediendo:

4. Primero de todo, durante la ejecución del Trigger prevalece el trace flag del Trigger, es decir,
se aplican los niveles establecidos en “LOGCOMPLETO” sobre “TODONONE”, que como has
visto en su definición solicita todos los eventos disponibles de todas las categorías (es el
máximo nivel de log configurable para todas las categorías).

5. Pero, y aquí viene la confusión, el Trace Flag “LOG_COMPLETO” no solo se aplica al código
del Trigger, sino que también se aplica a las 2 clases que se ejecutan dentro del mismo
contexto, dado que se produce herencia del Trace Flag sobre las 2 clases AddressChanger y
DescriptionChanger.

Y es por eso que el log generado es más voluminoso de lo esperado si desconoces cómo funciona
la herencia, y los usuarios se sorprenden cuando “solo” han configurado obtener un trace flag
sobre el Trigger.

Entonces seguramente te estás preguntando “¿Puedo evitar esta situación?” En un proyecto real
esto puede desencadenar en un alud de log no deseado.
La respuesta es que sí se puede evitar, aplicando la técnica de Filtering.

14.2 En qué consiste el Filtering de Logs


La técnica de Filtering de logs no es un nuevo mecanismo que debemos aprender sino reaplicar
la técnica de sobrescritura que se lleva a cabo al activar un trace flag de tipo CLASS_TRACING.

Dado que se aplica la herencia cuando defino un trace flag para una clase o un Trigger, pero no
queremos que se aplique sobre todas las clases ejecutadas en el contexto, podemos utilizar el
mecanismo de sobrescritura para aplicar un trace flag distinto (adecuado, diría mejor) para
aquellas clases invocadas en el contexto de ejecución, y esto se denomina Filtering.

Como estarás pensando, es un proceso tedioso, y tienes razón.

Veamos las configuraciones necesarias y el resultado obtenido al generar log “solo para el
Trigger”:

23
https://bitbucket.org/estevegraells/libro-la-guia-definitiva-para-dominar-el-log-de-
salesforce/src/master/logs/Log__Creacion_Account_Overloading.log

70
Herencia y Filtering de logs

Ilustración 54 - Definición de trace flag sobre clase Apex

Ilustración 55 - Descripción de trace flag sobre otra clase Apex

El log generado son 110 líneas, no se ha generado log perteneciente a las 2 clases.

En este ejemplo tan simple con tan solo 2 clases, hemos evitado la generación de 36 líneas de log
(puedes descargar el log obtenido aquí: Log con Filtering24), pero en un proyecto real con
numerosas clases, serán muchas más las líneas que evitarás generar, obteniendo un log más
concreto en lo que quieres analizar (y no malgastarás el límite de 1.000 MB).

Puedes ver en esta tabla un resumen de lo tratado en este capítulo, que te puede servir para
afianzar lo que hemos visto:

Qué log quiero generar Qué tengo que hacer


Definir un Trace Flag para el Trigger, la herencia se
Quiero generar log para el
propagará hacia las 2 clases y tendrás un log completo de
Trigger y las 2 clases.
los 3 elementos.
Definir un Trace Flag para el Trigger. Definir un Trace Flag
Quiero generar log solo para el para cada clase: uno para AddressChanger y otro para
Trigger. DescriptionChanger, que provocarán un Overloading, y
evitarán el efecto de herencia.

24 https://bitbucket.org/estevegraells/libro-la-guia-definitiva-para-dominar-el-log-de-
salesforce/src/master/logs/Log__Creacion_Account_Solo_Trigger.log

71
La guía definitiva para dominar el Log de Salesforce

Definir un Trace Flag para el Trigger. Definir un Trace Flag


Quiero generar log para el
para la clase AddressChanger para deshacer la herencia. La
Trigger y solo para la clase
herencia se propagará hacia la clase DescriptionChanger y
DescriptionChanger.
el overloading lo impedirá sobre la clase AddressChanger.

72
Herencia y Filtering de logs

Bloque 2

73
La guía definitiva para dominar el Log de Salesforce

15. Cómo gestionar Logs con la API


Hasta ahora hemos visto cómo consultar los logs existentes, pero ¿podemos también gestionarlos
para crearlos, modificarlos y eliminarlos programáticamente? Pues sí.

Completemos la tabla que vimos anteriormente:

Accesible vía SOQL //


Capacidad Accesible vía Tooling API
API REST Query
Obtener el listado de los Sí, vía query al objeto
Sí, vía query al objeto ApexLog
logs existentes ApexLog
Obtener los datos de
Sí, vía el objeto ApexLog Sí, vía el sobject ApexLog
cabecera de un log
Obtener el cuerpo de un
No Sí, vía el sobject ApexLog
Log generado (Body)
Gestionar Debug Levels No Sí, vía el sobject DebugLevel
Gestionar Trace Flags No Sí, vía el sobject TraceFlag

Por lo tanto, la Tooling API permite gestionar todos los elementos relacionados con los logs.

15.1 Gestionar logs generados con la API


15.1.1 Crear o modificar un log
Con la API podemos crear/modificar/eliminar un Trace Flag, pero no podemos crear ni modificar
los logs existentes ya generados, pero sí eliminarlos.

De hecho, no te puedo mostrar directamente cómo crear o modificar un Trace Flag, ¿sabes por
qué? Pues porque como vimos para crear un Trace Flag necesitamos un nivel de Debug.

Veremos cómo crear un nivel de debug de inmediato, déjame antes mostrarte cómo eliminar un
log.

15.1.2 Eliminar un Log con la API


Dado que conocemos el recurso /sobjects/ApexLog/id/ para consultar logs, podemos tan solo
cambiando el verbo HTTP a DELETE eliminar logs, como puedes ver en este ejemplo:

Ilustración 56 - Invocación de API para eliminar log

74
Cómo gestionar Logs con la API

Y si volvemos a preguntar por ese log, la respuesta es NOT FOUND:

Ilustración 57 - Invocación de API después de haber eliminado log

15.2 Gestionar Debug Level con la API


Para crear un Trace Flag, necesitamos previamente un Debug Level, seguro que a estas alturas lo
tienes claro como el agua.

Un Debug Level es el conjunto de asignaciones para cada una de las categorías con un nivel de
log (que es un conjunto de eventos agrupados).

Por ejemplo, recordemos cómo es la definición de SFDC_DevConsole:

Ilustración 58 - Descripción del nivel de Debug SFDC_DevConsole

75
La guía definitiva para dominar el Log de Salesforce

La Tooling API proporciona gestión completa a los Debug Levels: consultar, crear, eliminar y
modificar; veamos, pues, cómo hacerlo.

15.2.1 Consultar los Debug Levels vía API


En la siguiente captura, podemos ver cómo he obtenido los Debug Levels existentes, donde, cómo
no, aparece el famoso SFDC_DevConsole:

Ilustración 59 - Obtención de la lista de logs mediante API

15.2.2 Creación de un Debug Level vía API


La creación de un nuevo Debug Level se asemeja a las invocaciones anteriores con la Tooling API:

Ilustración 60 - Creación de un nivel de log mediante API

76
Cómo gestionar Logs con la API

15.2.3 Modificación de un Debug Level vía API


Podemos modificar un Debug Level existente utilizando una invocación con el verbo PATCH y
adecuando el recurso al que accedemos.

En la siguiente captura he modificado el Debug Level recientemente creado, modificando los


atributos DeveloperName y MasterLabel y aumentando el nivel de log para la categoría ApexCode
con el valor FINEST.

Ilustración 61 - Modificación de nivel de debug mediante invocación API

Volviendo a consultar este Debug Level concreto, obtenemos que el cambio se ha efectuado
correctamente:

Ilustración 62 - Resultado obtenido de modificación de nivel de debug mediante API

15.2.4 Eliminación de un Debug Level vía API


Finalmente, para eliminarlo solo se requiere el cambio del verbo HTTP, y se lleva a cabo la
eliminación:

77
La guía definitiva para dominar el Log de Salesforce

Es muy importante que recuerdes que al eliminar un Debug Level, automáticamente todos los
Trace Flags que lo estuvieran utilizando también se borrarán.

15.3 Gestionar Trace Flags con la API


Habiendo visto cómo creamos un Debug Level (nivel de debug) podemos gestionar los Trace
Flags. La Tooling API nos permite crear, modificar y borrar Trace Flags:

• Crear un Trace Flag nos permite programar cuándo queremos que se generen logs;
recuerda que su fecha de inicio no debe ser el momento presente, sino que debe ser una
fecha de inicio futura.

• Modificar un Trace Flag nos permite adecuar uno actualmente existente.

• Eliminar un Trace Flag nos permite finalizar la generación de logs procedentes de este
Trace Flag.

Veamos en detalle cada una de estas acciones con ejemplos prácticos:

15.3.1 Consultar los Trace Flags vía API


En esta captura te muestro todos los Trace Flags que están reportando como ApexCode=FINEST:

78
Cómo gestionar Logs con la API

Ilustración 63 – Obtención de listado de Trace Flag mediante API

Para la gestión de los Trace Flags el endpoint es equivalente a los que vimos anteriormente:
/services/data/v{{version}}/tooling/sobjects/traceflag con los verbos GET, POST, PATCH y
DELETE.

Aquí van algunos ejemplos:

• Obtener el detalle de un trace flag mediante su ID:


{{_endpoint}}/services/data/v{{version}}/tooling/sobjects/TraceFlag/7tf09000001q0S
kAAI

Ilustración 64 - Obtención de detalle de un log mediante API

79
La guía definitiva para dominar el Log de Salesforce

• Obtener todos los trace flags:


{{_endpoint}}/services/data/v{{version}}/tooling/query/?q=SELECT+Id+FROM+TraceFlag

• Obtener los trace flags para clases APEX; recuerda que los posibles valores son
CLASS_TRACING, DEVELOPER_LOG, USER_DEBUG:
{{_endpoint}}/services/data/v{{version}}/tooling/query/?q=SELECT+Id+FROM+TraceFlag
+where+LogType='CLASS_TRACING'

• Obtener los trace flags que en su DEBUGLEVEL tienen el valor ApexCode=Finest;


evidentemente puedes hacer lo mismo para todos los otros niveles de DEBUG:
``{{endpoint}}/services/data/v{{version}}/tooling/query/?q=SELECT+Id+FROM+TraceFlag+w
here+ApexCode='FINEST'``

• Obtener aquellos trace flags que finalizan en un momento determinado:


{{_endpoint}}/services/data/v{{version}}/tooling/query/?q=SELECT+Id+FROM+TraceFlag
+WHERE+ExpirationDate=TODAY

• Obtener los trace flags que están asociados a una entidad:


{{_endpoint}}/services/data/v{{version}}/tooling/query/?q=SELECT+Id+FROM+TraceFlag
+WHERE+TracedEntityId='00509000000dfmQAAQ' concreta, por ejemplo un usuario
concreto.

15.3.2 Crear un Trace Flag vía API


Para crear un trace flag disponemos del verbo POST, pero requerimos 2 identificadores, que ya
sabemos cómo obtener:

• El ID de la entidad que vamos a tracear, que habitualmente será un usuario.

• El ID del Debug Level.

Ilustración 65 - Creación de un Trace Flag mediante API

15.3.3 Modificar un Trace Flag vía API


Modificar un trace flag mediante PATCH es una operación que tiene ciertas restricciones, ya que no
es posible modificar cualquier valor del Trace Flag:

• No es posible modificar la TracedEntityId, y de esta manera modificar el trace flag para


que genere el log para otro usuario.

• No es posible modificar el LogType, porque es un campo no modificable.

80
Cómo gestionar Logs con la API

• No es posible modificar el nivel de debug de una categoría concreta, es decir, una


operación de PATCH utilizando como body {ApexCode=“FINEST”} resulta en un error:

Ilustración 66 - Resultado obtenido al intentar modificar un Trace Flag mediante API


Por lo tanto, ¿cuándo es interesante modificar un Trace Flag? Pues, por ejemplo, para modificar el
campo ExpirationDate, que puede ser útil en ciertas circunstancias.

Ilustración 67 - Resultado obtenido al modificar con éxito un Trace Flag mediante API

15.3.4 Eliminar un Trace Flag vía API


Eliminar un Trace Flag requiere el cambio del verbo HTTP:

Ilustración 68 - Eliminación de un Trace Flag mediante API

81
La guía definitiva para dominar el Log de Salesforce

16. Cómo gestionar Logs con la SFDX CLI


Hasta ahora hemos visto cómo gestionar los diferentes elementos mediante APIs, pero además
tenemos otra alternativa para usar nuestra línea de comandos con el uso de la SFDX CLI25.

En los ejemplos a continuación, verás sentencias tanto en la Powershell de Windows, como


ejemplos ejecutados en la terminal de Mac OS. No existe diferencia en la sentencia entre ambos
sistemas al utilizar la SFDX CLI.

En el capítulo final de “Apéndices” he añadido 2 referentes al uso de Orgs mediante CLI y sobre la
librería JQ. Creo que ambos pueden ayudarte para optimizar el uso de la SFDX CLI.

16.1 Gestionar logs generados vía SFDX CLI


16.1.1 Consultar Logs vía SFDX CLI
En primer lugar, veamos cómo gestionar los logs que se han generado.

Ya vimos cómo listarlos con la sentencia force:apex:log:list, pero existe otra variante algo más
versátil si tienes conocimientos básicos de SOQL:

• sfdx force:data:soql:query -t -r human -q "SELECT Id, LastModifiedDate, Location,


LogLength, LogUserId, Operation, Request, StartTime, Status FROM ApexLog", donde el
parámetro más importante es -t, que indica que debe usarse la Tooling API para ejecutar
la consulta que aparece después del parámetro -q (de hecho, como ya vimos, no podemos
gestionar ni el nivel de debug ni el trace flag con la API REST, solo acceder a las cabeceras
de los logs).
Seguramene lo has deducido: -r human formatea el resultado, existiendo otras 2 opciones
más (CSV y Json).

Ilustración 69 - Obtención de logs mediante la CLI

25
https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference.htm

82
Cómo gestionar Logs con la SFDX CLI

Para obtener el detalle de un log incluyendo su contenido, tienes la siguiente sentencia (si utilizas
la opción --json podrás acceder a cada campo que necesitemos de forma programática e incluso
aprovechar librerías como jq26):

• sfdx force:apex:log:get -i 7dl09000000TR3tAAG, donde -i es el Id del log que


queremos obtener.

16.1.2 Eliminar un log vía SFDX CLI


Eliminar un log no tiene ningún misterio habiendo visto las sentencias anteriores:

• sfdx force:data:record:delete -s ApexLog -i 07L09000000D8SHEA0, incluso puedes


utilizar la opción -w para especificar un string a modo de condición para eliminar todos los
logs que cumplan ciertos criterios.

Si recuerdas, uno de los casos de uso habituales es realizar limpieza de los logs generados de
forma preventiva y así no superar el límite de 1.000 MB. No dejes de leer, porque si quieres borrar
varios logs, existen otras opciones.

16.2 Gestión de Debug Levels con SFDX CLI


16.2.1 Consultar Debug Levels con SFDX CLI
Para obtener un Debug Level concreto, y con lo que hemos visto ahora, tenemos la sentencia: sfdx
force:data:record:get -s DebugLevel -t -w "id=7dl09000000TR3tAAG", donde como criterio de
selección, el valor de un ID:

Ilustración 70 - Obtención de cabecera de log mediante CLI

Si queremos obtener todos los Debug Levels definidos, entonces ejecutamos una consulta contra
el objeto DebugLevel, como ya vimos: sfdx force:data:soql:query -t -r human -q "SELECT Id,
MasterLabel, DeveloperName, Language, ApexCode, ApexProfiling, Callout, System,
Validation, VisualForce, Workflow FROM DebugLevel"

26
https://stedolan.github.io/jq/

83
La guía definitiva para dominar el Log de Salesforce

Ilustración 71 - Obtención de niveles de debug mediante CLI

16.2.2 Crear Debug Level vía SFDX CLI


Para crear un Debug Level ejecuta la sentencia, donde especificas todos los valores necesarios:
sfdx force:data:record:create -s DebugLevel -t -v
"DeveloperName=Nuevo_Debug_Level_Desde_CLI MasterLabel=Nuevo_DL_CLI ApexCode=INFO
ApexProfiling=INFO Callout=DEBUG Database=FINEST System=DEBUG Validation=FINE
Visualforce=FINEST Workflow=WARN"

Ilustración 72 - Creación de un nivel de debug mediante CLI

16.2.3 Modificar Debug Level vía SFDX CLI


Para modificar un Debug Level quizás el comando más sencillo sea: sfdx
force:data:record:update -t -s DebugLevel -i "7dl09000000TSbIAAW" -v "APEXCODE=FINER",
donde estoy modificando el nivel de log para la categoría de ApexCode.

• Pero ¿y si quieres modificar varios logs al mismo tiempo? No puedes utilizar sfdx
force:data:record:update, ya que únicamente permite modificar un registro. Si estás
pensando en utilizar sfdx force:data:bulk:upsert, lo siento mucho, pero no soporta la
opción -t para utilizar la Tooling API.
A continuación, te adjunto un script de bash que he realizado que lleva a cabo esta tarea
(requiere la librería jq instalada; si no sabes cómo utilizar esta librería, en el apartado de
“Apéndices”, al final de esta guía, te explico cómo hacerlo) y es un buen ejemplo para
entender cómo la CLI nos permite automatizar tareas para la gestión de logs:

#Obtener todos los Debug Level existentes


DEBUG_LEVELS_IDS=$(sfdx force:data:soql:query -t -q "SELECT Id FROM DebugLevel WHERE
ApexCode='FINER'" -r "json" | jq '.result .records[] .Id' -r)

#Para cada DebugLevel modificar el valor del level de la categoría ApexCode


for debug_level_id in $DEBUG_LEVELS_IDS
do
echo $(sfdx force:data:record:update -t -s DebugLevel -i $debug_level_id -v
"APEXCODE=FINER")
done

En este script, asigno a la variable DEBUGLEVELSIDS el resultado de consultar los IDs de los
Debug Levels, que en este caso he filtrado para obtener aquellos que tienen el ApexCode=INFO.

A este resultado obtenido en formato json, le aplico una pipe, y usando la librería jq obtengo los
nodos IDs.
84
Cómo gestionar Logs con la SFDX CLI

Para cada ID obtenido realizo la modificación invocando la CLI con el comando sfdx
force:data:record:update.

16.2.4 Eliminar Debug Level vía SFDX CLI


Para eliminar un Debug Level utiliza una sentencia como sfdx force:data:record:delete -s
DebugLevel -t -i "7dl09000000TSaUAAW".

Puede que te soliciten proporcionar un mecanismo para eliminar varios Debug Levels en función
de un criterio, como a mí me ha pasado: te facilito el siguiente script de bash análogo al anterior:

#!/bin/bash
#Obtener todos los debug levels cuyo categoría ApexCode tenga el level INFO
DEBUG_LEVELS_IDS=$(sfdx force:data:soql:query -t -q "SELECT Id FROM DebugLevel WHERE
ApexCode='INFO'" -r "json" | jq '.result .records[] .Id' -r)

# Eliminar todos los Debug Levels obtenidos


for debug_level_id in $DEBUG_LEVELS_IDS
do
echo $(sfdx force:data:record:delete -t -s DebugLevel -i $debug_level_id)
done

16.3 Gestionar Trace Flags vía SFDX CLI


16.3.1 Consultar los Trace Flags vía SFDX CLI
Para obtener todos los trace flags invoca la sentencia sfdx force:data:soql:query -t -r human -
q "SELECT Id, ExpirationDate, ApexCode, Callout, TracedEntityId FROM TraceFlag"

Ilustración 73 - Obtener listado de trace flags mediante CLI

Con lo que obtener un trace flag casi no necesita explicación: sfdx force:data:record:get -s
TraceFlag -t -i "7tf09000001qsURAAY"

Ilustración 74 - Resultado obtenido para consultar un trace flag mediante CLI

85
La guía definitiva para dominar el Log de Salesforce

16.3.2 Crear un Trace Flag vía SFDX CLI


Para crear un trace flag, debemos conocer el ID de la entidad a trazar (un usuario) y el ID del
Debug Level, que creamos en los apartados anteriores. Para ello, voy a realizar las siguientes
sentencias:

• Para obtener el User ID: sfdx force:data:record:get -s User -w "FirstName=Esteve" |


grep Id ó alternativamente sfdx force:data:soql:query -t -q "SELECT Id FROM User
WHERE FirstName='Frodo'"

• Para obtener el ID del Debug Level: sfdx force:data:soql:query -t -q "SELECT Id,


DeveloperName FROM DebugLevel WHERE DeveloperName=SoloApexWarn"

• Y con los valores obtenidos en las 2 sentencias anteriores, ejecuto la creación sfdx
force:data:record:create -s TraceFlag -t -v "TracedEntityId=00509000000e4K6AAI
DebugLevelId=7dl09000000TSaUAAW ExpirationDate='2020-10-28T23:00:00.000+0000'
LogType=USER_DEBUG"

Ilustración 75 - Creación de un trace flag mediante CLI

16.3.3 Modificar un Trace Flag vía SFDX CLI


Una de las operaciones más habituales para modificar un trace flag es alterar su DebugLevelId
para aumentar o disminuir el número de eventos a recibir en el log; la sentencia sfdx
force:data:record:update -t -s TraceFlag -i 7tf09000001rLjPAAU -v "DebugLevel
Id=7dl09000000TSaUAAW ExpirationDate='2020-10-28T23:00:00.000+0000'", realiza esta operación
teniendo en cuenta que debe incluirse el campo ExpirationDate.

Ilustración 76 - Modificación de un trace flag mediante CLI

16.3.4 Eliminar un Trace Flag vía SFDX CLI


Finalmente, para eliminar un trace flag: sfdx force:data:record:delete -t -s TraceFlag -i
7tf09000001qsURAAY, como en el ejemplo siguiente:

86
Casos de uso habituales en los proyectos

17. Casos de uso habituales en los proyectos


17.1 Caso 1: Cómo borrar todos los Logs de un
plumazo
En esta guía leerás muchas veces que existen límites para el log en la plataforma. Uno de ellos es
el límite del almacenamiento, que en el momento de escribir esta guía es de 1.000 MB.

Puede parecer suficiente, pero te puedo asegurar que si no llevas a cabo un proceso de limpieza
para eliminar logs, acabarás consumiendo todo el espacio.

Para ello, te recomiendo que valores los pasos que te comento a continuación o que se los
sugieras al administrador de la ORG (también tienes disponible este video de Salesforce titulado
How to Delete Debug Logs in Chunks27):

1. Entrar en la Developer Console y ejecutar la consulta SELECT Id FROM ApexLog, para obtener
todos los IDs de los logs generados.
Seguramente no podrás borrar todos los logs, porque hay otros compañeros trabajando con
ellos.
Para ello te recomiendo usar esta consulta en su lugar:
SELECT id, LogLength FROM WHERE ApexLog ORDER BY LogLength DESC,
o incluso empezar por esta otra: SELECT id, LogLength FROM WHERE Location=‘Monitoring’
ApexLog ORDER BY LogLength DESC.

Con esta consulta obtienes los logs que más espacio ocupan y del tipo Monitoring, que son
los mejores candidatos que eliminar. Habiendo confirmado que puedes borrarlos, pasa al
siguiente paso.
Puedes construir otras consultas para obtener logs que puedan ser eliminados: ordenar por
fecha, ordenar por creador, etc.

2. Marca la opción de Uso de la Tooling API, que aparece en la parte inferior de la pantalla.

3. Ahora debes seleccionar las filas de los logs que deseas borrar. Si tienes más de 2.000 logs
generados, debe repetirse esta acción en tandas de 200.

4. Haz click sobre el botón de Delete Row. Recuerda que no hay vuelta atrás cuando hayas
eliminado los logs.

27
https://youtu.be/rwORE5T39C4

87
La guía definitiva para dominar el Log de Salesforce

Ilustración 77 - Acciones para eliminar logs en la Developer Console

Como ves, este proceso tiene ciertos inconvenientes:

• Es un proceso manual, requiere cierto tiempo para llevarlo a cabo, y alguien con
determinados conocimientos.

• Requiere de acceso al entorno, lo que puede consumir tiempo, o no ser posible, porque hay
entornos donde solo ciertos usuarios administradores pueden acceder para realizar
funciones muy determinadas.

Veamos, a continuación, cómo automatizar este proceso.

17.1.1 Automatizando este proceso


Mediante el uso de la CLI podemos automatizar el borrado de los logs generados.

A continuación, te propongo los siguientes comandos, que te pueden servir como base para crear
tu propia automatización:

1. Obtener todos los ID de los Logs quedando almacenados en un fichero CSV:


sfdx force:data:soql:query -q "SELECT Id FROM ApexLog" -r "csv" > IDsLogsBorrar.csv

2. Eliminar todos los logs mediante este comando: sfdx force:data:bulk:delete -s ApexLog -f
IDsLogsBorrar.csv

Es decir, con estas 2 sentencias puedes eliminar todos los logs del sistema.

Como te comentaba en el apartado anterior, muy probablemente no quieras borrar todos los logs
existentes, de ahí que tendrás que adaptar la que te propongo, para eliminar por ejemplo los logs
más antiguos de ciertos días, etc.

Si puedes establecer con los miembros del proyecto una política de borrado diaria o semanal de
logs, evitarás sorpresas.

Aun así, ¿puede ser que algún participante cree un trace flag que genere tanto log que desborde
el almacenamiento? Pues sí, es posible.

88
Casos de uso habituales en los proyectos

Por ello, además de un proceso de mantenimiento de limpieza regular, y con el conocimiento que
tienes ahora del uso de la API y de la CLI, ¿crees posible construir scripts de automatización que
consulten el tamaño de todos los logs generados y que compruebe si se acercan peligrosamente a
un % límite y que envíe una alarma a los componentes del proyecto? Déjame responderlo por ti: la
respuesta es que sí puedes, y te recomiendo que lo tengas disponible al menos en los entornos
críticos.

17.2 Caso 2: Obtener los Logs del entorno de PRO


si no tengo acceso
Supongamos que durante el análisis de una incidencia no es posible reproducirla en los entornos
a los que tenemos acceso. En esta situación lo más habitual es crear un trace flag para ese
usuario e intentar reproducir la incidencia en ese entorno.

Este proceso es algo engorroso, ya que no solo debemos acordar la disponibilidad del usuario,
sino que el administrador tiene que crear el trace flag correspondiente, proporcionarnos el log, etc.

Estos pasos en realidad son:

1. Obtener el ID del usuario, sabiendo que se llama Frodo Bolson.

2. Crear un DebugLevel que se adecúe a la incidencia, asociar categorías con niveles y obtener
su ID una vez creado.

3. Crear un Trace Flag que se inicie a las 8 de la mañana (por si el usuario se conecta pronto o se
va tarde) y que esté activo durante 24 horas.

4. Cuando el usuario nos confirma que ya ha repetido la incidencia, descargar los logs y enviarlos
a quien deba analizar la incidencia.

5. Esta persona debe analizar el log generado, para entender la incidencia.

6. Ofrecer un Fix, que deberá ser incluido en un Commit, seguramente mediante un


procedimiento de HotFix.

Todos los pasos anteriores deben repetirse hasta cerciorarse que el bug ha sido corregido.

7. Eliminar los logs.

8. Eliminar el DebugLevel creado, con lo que automáticamente se eliminará el TraceFlag también.

Como puedes ver, los pasos no son pocos, y quizás la disponibilidad del administrador no es total,
con lo que ¿no sería interesante disponer de una automatización de todos estos pasos?

Veamos cómo hacerlo:

Paso 1: obtener el ID de un usuario “tan famoso” es sencillo con una query: sfdx
force:data:soql:query -q "SELECT Id FROM User WHERE FirstName='Frodo' AND
LastName='Bolson'", o alternativamente sfdx force:data:record:get -s User -w

89
La guía definitiva para dominar el Log de Salesforce

"FirstName=Frodo LastName=Bolson" | grep Id, aunque yo prefiero la primera opción, cuyo


resultado es:

Querying Data... done


ID
──────────────────
00509000000e4K6AAI
Total number of records retrieved: 1.

Paso 2: como no sabemos exactamente qué puede estar pasando, vamos a activar varias
categorías a FINEST. Atención, dado que dependiendo del volumen de logs que ya tengamos
generados y los que generemos puede producirse un truncado de los logs anteriores.

sfdx force:data:record:create -s DebugLevel -t -v "DeveloperName=INCIDENCIA_08062007


MasterLabel=INCIDENCIA_08062007 ApexCode=FINEST ApexProfiling=FINEST Callout=INFO
Database=FINEST System=DEBUG Validation=NONE Visualforce=NONE Workflow=DEBUG"

La ejecución de esta sentencia genera un resultado tal que:

Creating Record for DebugLevel... done


Successfully created record: 7dl09000000TUdBAAW.

Paso 3: aunque en la documentación no queda claro, existe la posibilidad de indicar StartDate


como campo de creación y así programar la creación de un Trace Flag. Debes ir con cuidado
porque el horario utilizado debe estar acorde al horario de la instancia:

sfdx force:data:record:create -s TraceFlag -t -v "TracedEntityId=00509000000e4K6AAI


DebugLevelId=7dl09000000TUdBAAW StartDate='2020-10-30T08:00:00.000+0000'
ExpirationDate='2020-10-31T08:00:00.000+0000' LogType=USER_DEBUG"

Cuyo resultado es:

Creating Record for TraceFlag... done


Successfully created record: 7tf09000001rSziAAE.

Paso 4: en estos momentos sabemos que el usuario ha replicado la incidencia; es el momento de


recuperar los logs.

Para ello, debemos obtener los IDs de todos los logs generados a partir de la fecha y hora, en
orden de creación (opcionalmente concatenar todos los logs, que es más cómodo para analizar).

#!/bin/bash
# Obtener todos los logs de un usuario, guardarlos y opcionalmente generar un fichero
con el log completo

#Obtenemos los IDs de los logs generados por el usuario


LOG_IDS=$(sfdx force:data:soql:query -t -q "SELECT Id FROM ApexLog WHERE
LogUserId='00509000000e4K6AAI' AND StartTime>2020-09-29T08:00:00.000+0000 ORDER BY
StartTime" --json | jq '.result .records[] .Id' -r)

i=1

for log_id in $LOG_IDS


do

echo $(sfdx force:apex:log:get -i $log_id > $i-$log_id.json) #Guardamos el log


descargado en un fichero con numeración secuencial

90
Casos de uso habituales en los proyectos

echo "Log con ID: " $log_id.json " descargado y renombrado a " $i-$log_id.json

cat $i-$log_id.json >> log_completo.json # Opcionalmente generamos un fichero único


de log

((i=i+1))
done

Paso 5: una vez hemos descargado los logs de este usuario, realizamos limpieza, eliminándolos
con la sentencia sfdx force:data:record:delete -t -s ApexLog -i 07L09000000D8SHEA0

#!/bin/bash

#Obtenemos los IDs de los logs generados por el usuario y quedan almacenados en un
fichero CSV
echo $(sfdx force:data:soql:query -q "SELECT Id FROM ApexLog WHERE
LogUserId='00509000000e4K6AAI' AND StartTime>2020-09-29T08:00:00.000+0000" -r "csv" >
logs_a_borrar.csv )

# Ejecutamos un borrado masivo pasando como fichero de referencia


echo $(sfdx force:data:bulk:delete -s ApexLog -f logs_a_borrar.csv)

#Hacemos una comprobación


NUM_LOGS_USUARIO=$(sfdx force:data:soql:query -q "SELECT count(Id) FROM ApexLog WHERE
LogUserId='00509000000e4K6AAI' AND StartTime>2020-09-29T08:00:00.000+0000")
echo "El número de logs en el servidor son: " $NUM_LOGS_USUARIO

Paso 6: eliminar un registro para el cual tenemos el ID, a estas alturas, es muy sencillo:

sfdx force:data:record:delete -s DebugLevel -t -i 7dl09000000TUdBAAW, o alternativamente


también podemos optar por usar las denominaciones que usamos en la creación:
sfdx force:data:record:delete -s DebugLevel -t -w "DeveloperName=INCIDENCIA_08062007 Mas
terLabel=INCIDENCIA_08062007"

Para el paso 2, puedes proporcionarle al administrador un script muy práctico para crear
interactivamente un Debug Level y un Trace Flag: lo tienes disponible aquí: Creación DL-TF.sh28.

Es decir, podemos automatizar la creación de un trace flag para agilizar el análisis de una
incidencia de forma completa y sin afectar el estado del log.

17.3 Caso 3: Solo quiero ver el log de un Trigger o


una clase nada más
Vuelve al apartado Filtering de Logs, donde se detalla cómo aplicar esta técnica para obtener
exactamente el log deseado.

28
https://bitbucket.org/estevegraells/libro-la-guia-definitiva-para-dominar-el-log-de-
salesforce/src/master/scripts/CreacionDL-TF.sh

91
La guía definitiva para dominar el Log de Salesforce

17.4 Caso 4: Mantener un log siempre activo


No existe la posibilidad de mantener un log siempre activo más allá de 24 horas; aun así, con algo
de código es posible, renovando el Trace Flag. En el siguiente enlace te muestro el que
seguramente es el código más elegante que he encontrado para implementar este mecanismo:
James Simone - Building an apex Logging Service29.

29
https://james.coding.blog/apex-logging-service

92
Casos de uso habituales en los proyectos

Bloque 3

93
La guía definitiva para dominar el Log de Salesforce

18. Frameworks de Logs


En esta tercera parte, no puedo sino ceder a mis instintos, y si me conoces personalmente o
sigues mi blog, sabrás que soy fan de utilizar frameworks, es decir, entender cómo otras personas
han proporcionado una solución robusta a un problema concreto, para aprovechar su experiencia y
adaptarla a las necesidades que me aparecen.

Por ello, voy a analizar 4 frameworks que creo son muy adecuados porque aportan soluciones
distintas e innovadoras.

Para cada uno de ellos, te introduzco sus decisiones de diseño principales, donde encontrar las
fuentes, cuál es la metadata utilizada, cómo es el código implementado por el autor, cuál es el
resultado que obtendrás y, según mi opinión, cuáles son las ventajas e inconvenientes del
framework.

En ningún caso es mi intención valorar cuál es mejor o peor (aunque te diré cuál es mi favorito), ya
que para cada proyecto puede que se adapte mejor uno que otro, sobretodo dependerá de las
características y la situación del proyecto en qué estés.

En este punto, si no eres desarrollador, no abandones la lectura, los conceptos aplicados te


servirán igualmente para conversar con tus compañeros programadores.

18.1 Decisiones de diseño principales


Los frameworks que he analizado afrontan decisiones de diseño, que solucionan de forma distinta,
pero son las mismas decisiones que deberás tomar tú para implementar un framework. Estas son
las más importantes:

1. Mejorar el mecanismo de log de Salesforce versus sustituirlo completamente.

2. Dónde almacenar la información del log generado.

3. Cómo enviar esta información al repositorio elegido.

18.2 Framework 1: A handy Error Logger in


Salesforce to write the exceptions to a custom
object, de Md Noor Alam
He escogido este framework como primer ejemplo por varias razones:

• Es un framework ultrasencillo, pero ejemplifica claramente cómo complementar el log de


Salesforce sin sustituirlo.

• Utiliza un objeto Custom como repositorio de log, que es una de las decisiones de diseño
más comunes; esto permite analizar esta información mediante Reports, Dashboards, etc.,
para ser analizada.

94
Frameworks de Logs

• Es realmente sencillo, solo requiere una clase y pocas líneas, y aunque me atrevería a decir
que el código es mejorable, demuestra que ampliar el Log de nuestra plataforma sin
necesidad de ser un programador experto, es francamente posible.

En este framework el autor pretende complementar el log para ampliar la información cuando se
produce un error o una excepción en el código. Es un framework muy simple, pero creo que es
interesante para introducir algunas ideas principales.

18.2.1 Repositorios y enlaces interesantes


• Puedes encontrar el artículo original del autor aquí: A handy Error Logger in Salesforce to
write the exceptions to a custom object30.
• Puedes encontrar una versión comentada de este código realizada por mí, que creo te
puede ayudar a entender mejor este framework, aquí: http://bit.ly/log-MdNoorAlam.

18.2.2 Metadata utilizada


Este framework requiere de un objeto custom, que contiene los campos con la información para
almacenar el mensaje generado, el tipo, el nombre del método, etc., y 2 campos más que el autor
utiliza para informar del mensaje y la causa por la que se genera una excepción.

Ilustración 78 - Campos del objeto Exception Logger

18.2.3 Código
El código consiste en una sola clase que extiende la clase estándar Exception, ofreciendo:

• El método log(ex Exception)para generar una nueva entrada de log.

• Métodos auxiliares para introducir los valores de los campos para el módulo y la causa.

El resto de código consiste en extraer información de la instancia de Exception que recibimos y


escribir el registro en la base de datos.

30
https://medium.com/@noor.alam.shuvo/a-handy-error-logger-in-salesforce-to-write-the-exceptions-to-a-
custom-object-2b6f79e4c0ef

95
La guía definitiva para dominar el Log de Salesforce

Ilustración 79 - Esquema de clases

18.2.4 Cómo usarlo y resultado obtenido


Para utilizar el framework, el autor, al capturar la excepción, invoca los métodos de la clase
LogException, y finalmente invoca el método Log(ex), como puedes ver en el código a
continuación:

//Puedes encontrar código de uso en la clase de Test


try {
integer i = 1 / 0;
} catch (exception ex) {
new LogException()
.Module('unitTestModule')
.ExceptionCause('Division por 0')
.Log(ex);
}

Ejecuta este código como anónimo para obtener varias entradas en el objeto custom.

Habiendo creado una Tab para el objeto Custom y habiendo proporcionado acceso al perfil de mi
usuario y creado una List View como la siguiente, este es el resultado obtenido después de varias
ejecuciones del código anterior:

Ilustración 80 - Listado de registro del objeto Exception Logs

18.2.5 Ventajas e inconvenientes


• (V) Es un complemento al log de la plataforma y no un sustitutivo.

• (V) Es fácilmente comprensible y no requiere más allá de los conceptos básicos de


Salesforce y mínimos de programación.

• (V) El autor hace un uso interesante de chaining, para simplificar la escritura y lectura del
código.

• (I) Como todos los frameworks que utilizan un objeto custom, su uso impacta en el Data
Storage.

96
Frameworks de Logs

18.3 Framework 2: Creating Persistent Logs Using


Apex and a Custom Object, de Mayank
Srivastava
En este framework encontramos las siguientes características:

• Se propone una alternativa al log de Salesforce, no complementarlo.

• Se realiza mediante una implementación simple en Apex y accesible desde Javascript.

• También utiliza un objeto Custom como repositorio de log; esto permite analizar esta
información mediante Reports, Dashboards, etc.

18.3.1 Repositorios y enlaces importantes


• Puedes encontrar el artículo original del autor aquí: Creating Persistent Logs Using Apex and a
Custom Object31.
• Puedes encontrar una versión comentada de este código realizada por mí, que creo te puede
ayudar a entender mejor este framework, aquí: http://bit.ly/log-mayanksri.

18.3.2 Metadata utilizada


Una de las partes fundamentales de este Framework es el objeto custom, que puedes ver a
continuación:

Ilustración 81 - Campos del objeto Apex Debug Log

18.3.3 Código
Este es un esquema de las clases utilizadas:

31
https://succeedwithsalesforce.com/creating-persistent-logs-using-apex-and-a-custom-object/

97
La guía definitiva para dominar el Log de Salesforce

Ilustración 82 - Esquema de clases

El código está compuesto por una única clase global, ApexDebugLog, con las siguientes
características:

• Esta clase declara una clase interna virtual (Log) donde, únicamente mediante miembros,
se almacena la información.

• Dos clases especializadas (Information y Error) extienden la clase Log para fijar valores y
así ofrecer logs de los tipos Information y Error.

• Implementa 2 métodos miembros para:

• Generar log mediante la inserción de un registro en el objeto custom desde otras


clases Apex (el caso habitual).

• Generar log mediante la inserción de un registro en el objeto custom desde


Javascript ofreciendo un web service.

18.3.4 Cómo usarlo y resultado obtenido


Para utilizar el framework, sigo con el ejemplo anterior, pero esta vez, al capturar una excepción,
creamos una nueva entrada en el log, creando una instancia de la clase ApexDebugLog e invocando
el método createLog, cuyo parámetro es la instanciación de la clase Error.
//Puedes encontrar código de uso en la clase de Test
try {
Integer result = 1 / 0;
} catch (Exception ex) {
new ApexDebugLog()
.createLog(new ApexDebugLog.Error('ApexDebugLog_Test', 'createErrorLog', null,
ex));
}

Habiendo creado una Tab para el objeto Custom y habiendo proporcionado acceso al perfil de mi
usuario, puedes crear una List View como la siguiente y ver los registros de log generados:

98
Frameworks de Logs

Ilustración 83 - Listado de registro del objeto Apex Debug Logs

18.3.5 Ventajas e inconvenientes


• (V) Evita las limitaciones del log de Salesforce, persistiendo la información en un objeto
custom y garantizando así la perdurabilidad de la información, la búsqueda personalizada y
el borrado y/o archivado ad hoc.

• (V) La implementación es sencilla, pero ya utiliza conceptos más avanzados de


programación que permiten mayor flexibilidad utilizando una clase virtual.

• (I) El almacenamiento del objeto custom impacta en el consumo de Data Storage (el uso
de un Big Object podría aliviarlo).

• (I) Al utilizar una sentencia DML se consume este límite.

• (I) Sustituir completamente el sistema de Log de Salesforce comporta prescindir de todas


sus capacidades y obtener únicamente aquella información que generemos.

• (I) No utilizar métodos estáticos puede suponer un overhead importante en situaciones de


alta invocación de la clase.

Yo lo considero un primer enfoque al ofrecer una alternativa sustitutoria al log estándar de


Salesforce, y así evitar sus limitaciones.

Finalmente, déjame destacar el mayor inconveniente, y así aprovecho para introducir un concepto
importante. En la plataforma de Salesforce, tal y como puedes recordar en la documentación
oficial (Exceptions in Apex | Apex Developer Guide | Salesforce Developers32), cuando ocurre una
excepción, todas las operaciones DML que se habían ejecutado se cancelan y los cambios son
revertidos.

Por lo tanto, si durante el contexto de ejecución, cualquiera de nuestras clases, triggers, etc., o
cualquier código que haya aportado cualquier otro compañero o empresa, produce una excepción,
todo el log que hayamos querido registrar no será almacenado y no obtendrás ninguna entrada en
el log.

Veremos cómo solucionar esto más adelante, pero no quiero hacer spoiler aun, para variar.

32
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_definition.htm

99
La guía definitiva para dominar el Log de Salesforce

18.4 Framework 3: Forcelog - A structured,


extensible logger for Salesforce Apex, de OVO
Energy
Este framework me gusta especialmente, porque sin sustituir el log de Salesforce lo mejora
sustancialmente. No te escondo que además al usar los niveles de Syslog siento cierta nostalgia.

Las principales características de este framework son:

• Utiliza los niveles de Syslog, que son:

1. Emergency: el sistema está inutilizable

2. Alert: se debe actuar inmediatamente

3. Critical: condiciones críticas

4. Error: condiciones de error

5. Warning: condiciones de peligro

6. Alert: normal, pero condiciones notables

7. Info: mensajes informativos

8. Debug: mensajes de bajo nivel

• Proporciona métodos especializados para volcar objetos, listas de objetos, parejas clave-
valor, etc.

• Proporciona la capacidad de introducir Hooks, lo que permite realizar ciertas acciones


antes de volcar el log.

• Proporciona la capacidad de modificar el medio y la salida del log, por ejemplo, permite
volcar las entradas generadas al log de Salesforce, pero también enviarlas a un sistema
externo, o incluso dependiendo del entorno decidirlo dinámicamente.

• Está muy bien documentado.

18.4.1 Repositorios y enlaces importantes


• Puedes encontrar el artículo del autor en ForceLog: A structured, extensible logger for
Salesforce Apex33.
• Puedes encontrar el repositorio de código del Framework en
https://github.com/davidsbond/forcelog, y su wiki asociada aquí:
https://github.com/davidsbond/forcelog/wiki.

33
https://tech.ovoenergy.com/forcelog-a-structured-extensible-logger-for-salesforce-apex/

100
Frameworks de Logs

• Puedes encontrar mi repositorio con el código que yo he adaptado para una mejor
comprensión aquí: http://bit.ly/log-ovo.

18.4.2 Metadata utilizada


No utiliza metadata adicional, todo el framework está contenido en código.

18.4.3 Código
El código está organizado en una única clase denominada ForceLog, que contiene:

• Una clase interna denominada ReserveFieldException, que extiende la clase estándar


Exception.

• Otra clase interna abstracta denominada Logger, donde encontramos toda la lógica.

• Otra clase interna abstracta denominada BulkLogger, análoga a la anterior, pero que se
utiliza para volcar todo el log que vamos acumulando, en lugar de volcarlo cada vez que
invocamos una función de logging.

• Una interface denominada Hook que nos permite definir las funciones que se ejecutan
antes del volcado del log, y así permitir modificar las entradas del log que se van
generando.

18.4.4 Cómo usarlo y resultado obtenido


Para usar este Framework debemos:

• Extender la clase ForceLog.Logger.

• Para modificar el mecanismo de volcado del log debemos hacer un overrride del método
flush.

• Para introducir Hooks debemos proporcionar implementaciones de la interfaz Hookp y


añadirlos a la instancia del log mediante el método addHook.

Veamos un ejemplo algo cinematográfico de cómo utilizarlo:

/* Creo una clase, que podría ser cualquiera de las clases que tu utilizas en tu
proyecto. Seguramente tu implementación en el proyecto pasaría por utilizarlo como * un
método estático
*/
public with sharing class ProbandoOVOFramework {

//Declaro el logger como miembro de la clase


private LOTRLogger logger;

//Para usar ForceLog.Logger, lo extiendo


private class LOTRLogger extends ForceLog.Logger {
public LOTRLogger(String name) {
super(name);
}

/*
101
La guía definitiva para dominar el Log de Salesforce

El método flush original vuelca la entrada en el Log de Salesforce, por lo que no


tienes que sobrescribir este método para mantener esa funcionalidad. Si deseas
enviarlo a un sistema externo, deberías implementar este método de la siguiente
manera
*/
public override void flush(Map<String, Object> log) {
//Este método es ficticio
logToSomeExternalSystem(JSON.serialize(log));
}
}

/*
Implementa la interfaz hook para buscar el String "Sauron" y añadir información en el
log
*/
private class GollumHook implements ForceLog.Hook {

public void fire(Map<String, Object> log) {


for (Object o : log.values()) {
if (o.toString().contains('Sauron')) {
log.put('La edad de los hombres termina', 'El tiempo del orco ha llegado');
}
}
}
}

Pues ahora ya podemos ejecutar todos los métodos disponibles para generar entradas de log, que
son:

• 14 métodos para volcar información en función de los 7 niveles de Syslog. Por ejemplo,
para emergency tenemos 2 métodos:

• public void emergency(String message).

• public void emergency(String messageToFormat, List<String>


formattingArguments.

• Otros 2 métodos para clave-valor y lista de clave-valor.

• Otros 4 métodos para volcar objetos y lista de objetos.

• Otro método para volcar excepciones.

• Otros 6 métodos para volcar el objeto HttpReques.

• Otros 6 métodos para volcar el objeto HttpResponse.

• Otros 15 métodos para operaciones DML.

• Otros 3 métodos para volcar el objeto SendEmailResult.

Habiendo definido mi Logger, este es un ejemplo del uso de los métodos:

public ProbandoOVOFramework() {
//Instancia el Logger
logger = new LOTRLogger('Probando OVO Framework');

//Añado el Hook para filtrar

102
Frameworks de Logs

logger.addHook(new GollumHook());

//Invocaciones con los métodos del framework, solo algunos de los métodos
logger.debug('Probando Debug');
logger.info('Probando Info');
logger.info('Probando {0}', new List<String>{ 'Info' });

//Logear una pareja clave-valor


logger.withField('Bilbo', 'Bolson').critical('Nombre completo de Bilbo');

//Logear un array de claves-valor


logger.withFields(new Map<String, Object>{ 'Bilbo' => 'Bolson', 'Frodo' => 'Bolson' })
.info('Los Bolsones de la comarca');

//Logear el contenido de un objeto


Contact c = new Contact(FirstName = 'Sauron', Email = 'sauron@lacomarca.com');
logger.withSObject('sobject', c).emergency('Frodo está en peligro');

//Logear el contenido de una lista de objetos


List<SObject> bolsones = new List<SObject>{
new Contact(FirstName = 'Frodo', LastName = 'Bolson', Email =
'frodo@lacomarca.com'),
new Contact(FirstName = 'Bilbo', LastName = 'Bolson', Email = 'bilbo@lacomarca.com')
};
logger.withSObjects('sobjects', bolsones).notice('Viven en Bolson Cerrado');

//Logear indicando que ciertos campos sean excluidos


logger.withSObjects(
'Información sobre Bolsones',
bolsones,
new Set<String>{ 'FirstName', 'LastName' }
).info('No mostrar los nombres');

/*
Recuerda que están disponibles para: RestRequest, RestResponse, QueryLocator,
Database.SaveResult, Database.DeleteResult, Database.UpdateResult,
Database.MergeResult, Messaging.SendEmailResult, mediante los métodos:
withRequest, withResponse, withQuery, withResult, withResults
*/
}
}

Este es el resultado obtenido, donde puedes ver cómo el framework añade información en cada
invocación, y cómo se ha ejecutado el Hook:

09:08:19.73 (88430339)|USER_DEBUG|[26]|DEBUG|{"timestamp":"2020-12-
31T08:08:19.744Z","name":"Probando OVO Framework","level":"debug","message":"Probando
Debug"}

09:08:19.73 (88987923)|USER_DEBUG|[26]|DEBUG|{"timestamp":"2020-12-
31T08:08:19.746Z","name":"Probando OVO Framework","level":"info","message":"Probando
Info"}

09:08:19.73 (89518535)|USER_DEBUG|[26]|DEBUG|{"timestamp":"2020-12-
31T08:08:19.746Z","name":"Probando OVO Framework","level":"info","message":"Probando
Info"}

09:08:19.73 (90466659)|USER_DEBUG|[26]|DEBUG|{"Bilbo":"Bolson","timestamp":"2020-12-

103
La guía definitiva para dominar el Log de Salesforce

31T08:08:19.747Z","name":"Probando OVO Framework","level":"crit","message":"Nombre


completo de Bilbo"}

09:08:19.73
(92176544)|USER_DEBUG|[26]|DEBUG|{"Frodo":"Bolson","Bilbo":"Bolson","timestamp":"2020-
12-31T08:08:19.748Z","name":"Probando OVO Framework","level":"info","message":"Los
Bolsones de la comarca"}

09:08:19.73 (93356879)|USER_DEBUG|[26]|DEBUG|{"La edad de los hombres termina":"El


tiempo del orco ha
llegado","sobject":{"attributes":{"type":"Contact"},"FirstName":"Sauron","Email":"sauron
@lacomarca.com"},"timestamp":"2020-12-31T08:08:19.750Z","name":"Probando OVO
Framework","level":"emerg","message":"Frodo está en peligro"}

09:08:19.73
(94534053)|USER_DEBUG|[26]|DEBUG|{"sobjects":[{"attributes":{"type":"Contact"},"FirstNam
e":"Frodo","LastName":"Bolson","Email":"frodo@lacomarca.com"},{"attributes":{"type":"Con
tact"},"FirstName":"Bilbo","LastName":"Bolson","Email":"bilbo@lacomarca.com"}],"timestam
p":"2020-12-31T08:08:19.751Z","name":"Probando OVO
Framework","level":"notice","message":"Viven en Bolson Cerrado"}

09:08:19.73 (95906381)|USER_DEBUG|[26]|DEBUG|{"Información sobre


Bolsones":[{"Email":"frodo@lacomarca.com"},{"Email":"bilbo@lacomarca.com"}],"timestamp":
"2020-12-31T08:08:19.752Z","name":"Probando OVO Framework","level":"info","message":"No
mostrar los nombres"}

18.4.5 Ventajas e inconvenientes


• (V) El uso de los niveles de Syslog permite homogeneizar el log en un entorno empresarial
donde se utilice este estándar.

• (V) La posibilidad de definir hooks, para modificar el log antes de ser almacenado,
proporciona una solución a casos de uso, como filtrar datos sensibles, evitar mostrar según
qué campos, etc.

• (V) La posibilidad de redefinir la función de volcado mediante el método flush nos aporta
una flexibilidad y nos abre la posibilidad de enviar el log a otros sistemas de log que se
usen en nuestro entorno.

• (V) La posibilidad de usar BulkLogger, para minimizar el número de invocaciones al log, es


una optimización muy interesante, tampoco disponible en la funcionalidad estándar.

• (V) El uso de formato JSON para almacenar el log, en lugar de texto informal, permite
analizar la información de manera más eficiente.

• (V) La documentación existente, tanto en el repositorio oficial como en un artículo de un


empleado juntamente con el código de la clase de Test, son de gran ayuda para entender
cómo usar el framework y sus posibilidades.

• (I) La gran cantidad de métodos disponibles complica la implementación y el aprendizaje;


quizás es posible simplificar el framework sin tantos métodos.

104
Frameworks de Logs

Si consideraras este framework con el uso de Hooks, te aconsejo evaluar el uso del patrón Inversion of
Control34, especialmente para usar el framework en diferentes entornos (desarrollo, PRE, PRO, etc.).

18.5 Frameworks basados en Platform Events


Hasta aquí hemos visto frameworks que utilizan mecanismos “clásicos” y que en algunos casos
mantienen la funcionalidad del Log de Salesforce.

En los siguientes, veremos frameworks para la generación de log mediante el uso de de Platform
Events. Puedes encontrar un vídeo explicativo de esta técnica de Andrew Fawcett aquí: Advanced
Logging Patterns With Platform Events - YouTube35, y que posteriormente Dan Appleman plasma
en el capítulo 10 (en la versión que yo tengo, en la página 245) de su libro Advanced Apex
Programming in Salesforce36, cuya lectura te recomiendo, aunque no es imprescindible para
entender los frameworks que veremos a continuación.

18.5.1 Pero ¿por qué Platform Events?


En los frameworks que hemos visto hasta ahora, existe una debilidad importante, que ya
comentamos, pero repasémosla nuevamente:

• Si durante la transacción se produce una excepción en el código, o se lanza una excepción


de cualquier tipo, todas las operaciones DML (operaciones de base de datos que modifican
datos) que se hayan realizado serán desechas.

• Esto implica que si habías insertado registros en un objeto custom para almacenar
entradas de log, todas estas entradas serán descartadas, y te quedarás sin el propio log.

Esto se acentúa porque existen excepciones que no son atrapables, como la CPU time limit
Exception, lo que va a provocar abortar el contexto de ejecución en curso sin que puedas hacer
nada al respecto, y todas las operaciones DML serán deshechas.

Y aquí es cuando aparece el diseño de frameworks de log mediante Platform Events.

La idea es muy sencilla: al crear y enviar un Platform Event, éste se ejecuta en otro contexto, por lo
que la información que se haya adjuntado al evento estará disponible en otro contexto.

Si el contexto inicial se aborta por una excepción, el contexto en el que se ejecuta el evento no se
verá afectado y la información del log estará disponible para ser almacenada.

Pero ¿es posible obtener la información de la excepción y obtenerlo en mi log? Sí es posible: en el


código que ejecutas para atrapar la excepción, deberás generar un evento también.

34
https://developer.salesforce.com/blogs/2019/07/breaking-runtime-dependencies-with-dependency-
injection.html
35
https://www.youtube.com/watch?v=yYeurYnasVc
36
https://amzn.to/3qmrf8g

105
La guía definitiva para dominar el Log de Salesforce

18.5.2 Limitaciones al uso de Platform Events


Aunque seguramente estás bien informado sobre Platform Events, si no fuera el caso, te animo a leer
el siguiente artículo: Introducción a la Arquitectura de Eventos en Salesforce – Forcegraells37, o consulta la
documentación oficial38.

En este diseño mediante Platform events existen 2 limitaciones (Platform Events Allocations39):

1. El número de eventos disponibles por ventana de 24 horas y común a toda la Org. Este límite
es diferente en función de la edición que tengas: desde 10.000 eventos para una Developer
Org, hasta 50.000 para Performance and Unlimited Editions.

2. El número de eventos que pueden ser publicados en una 1 hora: que análogamente va desde
50.000 hasta 250.000 según la edición contratada.

Antes de decidirte por esta opción, comprueba si el volumen que vas a consumir no supera el
límite, dado que pueden existir otras funcionalidades en el proyecto que también estén
consumiendo Platform Events.

Este límite puede ser ampliado mediante suscripción a la licencia High Volume (consulta con tu
Salesforce Account Executive para ello).

A continuación, veremos 2 frameworks que abordan el uso de Platform Events y que además
tienen en consideración estas limitaciones.

18.6 Framework 4: Framework basado en eventos,


de Christian Szandor
Este framework se inspira en la descripción que realiza Dan Appleman en el capítulo 10 -
Debugging and Diagnostics de su libro Advanced Apex Programming -Fourth Edition40 (en la
versión que yo poseo es a partir de la página 233, en el apartado Instrumenting Apex - I).

Si no has leído el libro no te preocupes, estas son las características principales:

1. Implementa el concepto de push and pop para detectar la entrada y salida en los métodos.

2. Usa Platform Events para generar la información en un nuevo contexto de ejecución.

3. Almacena las entradas de log en un objeto custom.

37
https://forcegraells.com/2018/01/08/intro-arquitectura-eventos-salesforce/
38
https:/developer.salesforce.com/blogs/2019/07/breaking-runtime-dependencies-with-dependency-
injection.html
39
https://developer.salesforce.com/docs/atlas.en-
us.platform_events.meta/platform_events/platform_event_limits.htm

40 https://amzn.to/39qqCEh

106
Frameworks de Logs

4. Permite la selección de los logs que van a generarse mediante el uso de un Custom Metadata
Type, donde es posible filtrar por el nombre de las clases,

5. También permite filtrar la generación para ciertos usuarios que tienen asignado un Custom
Permission, etc.

6. Visualiza el log de una manera muy visual y acorde con la ejecución de los métodos que van
sucediendo.

7. Además, implementa un Lightning Web Component para obtener los eventos.

18.6.1 Repositorios y enlaces importantes


• Puedes encontrar el artículo original del autor en alemán (pero la mayoría de los navegadores
lo traducen) aquí: Ein Versuch über einen Protokoll-Service (shoreforce.herokuapp.com)41.
• Repositorio github: GitHub - Szandor72/logger: An attempt at a Salesforce Lightning Platform
Logging Service42.

18.6.2 Metadata utilizada


El framework utiliza diferentes capacidades de la plataforma, pero la más novedosa hasta ahora en
cuanto a diseño es el uso de un Platform Event:

Ilustración 84 - Platform Event definido en el framework

También utiliza un Custom Metadata Type, denominado Logger Configuration, donde


seleccionamos las opciones de generación de log:

41 https://shoreforce.herokuapp.com/ein-versuch-uber-einen-protokoll-service/

42
https://github.com/Szandor72/logger

107
La guía definitiva para dominar el Log de Salesforce

Ilustración 85 - Custom Metadata Type definido en el Framework


Fwkszandor-CustomMetadataType

Además, también utiliza un Custom Permission, denominado Enable Logging, que forma parte del
Permission Set llamado Log This User, que permite activar el log para los usuarios que lo tienen
asignado:

Ilustración 86 - Custom Permission definido en el Framework

Ilustración 87 - Permission Set definido en el Framework

18.6.3 Código
El autor utiliza las siguientes clases:

• La clase Logger, donde encontramos la mayoría de la lógica del Framework, a excepción de


la captura del evento y la inserción en el objeto custom.

• La clase LoggerConfig, que obtiene la inicialización y lectura del Custom Metadata Type.

• La clase DebugEntryService, que utiliza para obtener la información del evento generado e
insertarlo en la base de datos.

• Un trigger denominado Logs.trigger, para capturar los eventos generados que invoca la
clase DebugEntryService.

108
Frameworks de Logs

18.6.4 Cómo usarlo y resultado obtenido


Para conseguir que el framework funcione, despliega el código en una Sandbox, preferiblemente
en una scratch org, y sigue estos pasos:

1. Asigna el Permission Set denominado Logger Permissions al usuario que quieras que tenga
acceso a la aplicación que ha creado el autor.

2. Si quieres usar la Utility bar disponible en la aplicación debes asignarla, ya que no lo está.

3. Para las pruebas iniciales te recomiendo que el flag Log Messages Only / Live View esté
deshabilitado en el registro denominado Default del Custom Medatata Setting denominado
Logger Configuration.

1. Solo se utiliza un registro Logger Configuration, por lo que si tienes varios, te


recomiendo que solo tengas uno con el flag is Active a true.

4. Te recomiendo que crees la clase de ejemplo que te muestro a continuación, que creo que te
ayudará a entender el resultado obtenido. Para ejecutarla tan solo ejecuta new Handler() como
Apex anónimo.

public with sharing class Handler {


public Handler() {

Logger.push();
Logger.Log('Estoy en el Constructor');
routine1();
routine2();
Logger.pop();
}

public void routine1() {


Logger.push();
//Este mensaje es redundant
Logger.Log('Estoy en routine1');
Logger.log('Invoco a subroutine1');
subroutine1();
Logger.pop();
}

public void routine2() {


//Este mensaje es redudante
Logger.Log('Entrando en routine2');
Logger.push();
Logger.log('Invoco a subroutine2');
subroutine2();
Logger.pop();
}

public void subroutine1() {


Logger.push();
//Aunque no añada ninguna sentencia Logger.log podemos observar en el Log
//que se ejecuta este método
Logger.pop();
}

109
La guía definitiva para dominar el Log de Salesforce

public void subroutine2() {


Logger.push();
Logger.log('Invoco a subroutine3 y subroutine4');
subroutine3();
subroutine4();
Logger.pop();
}

public void subroutine3() {


Logger.push();
Logger.log('Ejecutando Lógica de negocio en subroutine3');
subroutine4();
Logger.pop();
}

public void subroutine4() {


Logger.push();
Logger.log('Volcado de stacktrace: ' + Logger.stackTrace);
Logger.pop();
}

También puedes probar el framework desde un trigger; este es el código que yo he utilizado:

trigger AccountTrigger on Account (before insert) {


Logger.logTrigger();
Logger.log('Logica de negocio');
new Handler();
Logger.logTrigger();

El resultado obtenido es un conjunto de registros en el objeto DebugEntry__c, que son las entradas
de log generadas. Verás en las siguientes capturas cómo el autor formatea el código, de manera
que facilita mucho su lectura:

Ilustración 88 - Listado de registros en el objeto Debug Entries

110
Frameworks de Logs

Ilustración 89 - Ejemplo de log formateado por el framework

Y para el código del Trigger, de la misma manera:

Ilustración 90 - Log generado para el Trigger

Cuando activas el flag Log Messages Only / Live View, recibirás los eventos en la Utility Bar, que
debes insertar en la página previamente:

Ilustración 91 - Ejemplo de los eventos capturados en la Utility Bar

18.6.5 Ventajas e inconvenientes


• (V) Evita las limitaciones del Log de Salesforce, persistiendo la información en un objeto
custom y garantizando así la perdurabilidad de la información, la búsqueda personalizada y
el borrado y/o archivado ad hoc. Esto permite analizar esta información mediante Reports,
Dashboards, etc., para ser analizada.

• (V) Es un complemento al log de la plataforma y no un sustitutivo.

• (V) Mediante el uso de Platform Events se robustece la implementación del framework.

111
La guía definitiva para dominar el Log de Salesforce

• (V) El framework proporciona mecanismos de filtrado para no generar logs que no


necesitamos.

• (I) Como todos los frameworks que utilizan un objeto custom, el uso de un objeto custom
impacta en la cantidad de Data Storage consumido.

• (I) El uso de Platform Events requiere tener cierto conocimiento y analizar las limitaciones
que nos impone la plataforma.

• (I) Requiere de cierto tiempo de testing y comprensión del código, ya que no es muy
amplia la documentación existente, ni tampoco en ejemplos, y se basa en conceptos de
otros autores que es mejor conocer previamente.

18.7 Framework 5: ApexLogger de Mike Lockett


Finalmente, llegamos al framework que puedo decir es mi predilecto, ya que, basado en Platform
Events, proporciona una excelente base de funcionalidades que coinciden con muchos
requerimientos que me he encontrado en varios proyectos.

Sus principales características son:

1. Implementa el uso de Platform Events para generar la información en un nuevo contexto de


ejecución.

2. Almacena las entradas de log en un objeto custom; esto permite analizar esta información
mediante Reports, Dashboards, etc., para ser analizada.

3. Permite filtrar datos sensibles mediante expresiones regulares para ser sustituidas por otros
valores que permitan seguir la pista de ciertos datos pero sin publicarlos, y además lo hace de
una manera simple.

4. Permite filtrar las trazas por Level y usuario mediante un Custom Metadata Type (de manera
semejante a como ya vimos en el framework anterior).

5. Permite invocar la función del log desde Process Builder (se declaran un método
@InvocableMethod denominado WriteLog), lo que nos permite generar logs mediante una
sentencia de tipo Apex.

6. Existe documentación suficiente.

18.7.1 Repositorios y enlace importantes


• Puedes encontrar el artículo original del autor en Advanced Logging43.
• Puedes encontrar el repositorio del código del autor en
https://github.com/mlockett/ApexLogger, donde existe información adicional del framework

43
https://objectfactory.ws/tech/log.php

112
Frameworks de Logs

(cómo usarlo desde Process Builder, cómo crear filtros sobre datos sensibles mediante
expresiones regulares y sustituirlas por otras cadenas, etc.).

18.7.2 Metadata utilizada


Como seguro esperas, existe un Platform Event definido:

Ilustración 92 - Platform Event definido en el framework

Los campos custom de este evento son todos de tipo textual, donde se registra la información que
será almacenada en el objeto custom, que es el siguiente:

Ilustración 93 - Campos definidos en el objeto AppLog

Existen 2 Custom Metadata Types (aunque en el código encontrarás 3, el Log Filter no se usa):

Ilustración 94 - Custom Metadata Types definidos en el framework


Fwklockett-DefinicionCustomMetadataTypes
• Log Message Filter: permite definir las expresiones regulares para sustituir ciertos
patrones de texto por otros u ocultarlos.

113
La guía definitiva para dominar el Log de Salesforce

• Log Record Filter: permite definir los usuarios y los niveles para almacenar las entradas
de log. Esta funcionalidad permite restringir para qué usuarios en cada uno de los entornos
queremos registrar logs y con qué nivel de log (por ejemplo: INFO, DEBUG, WARNING,
ERROR, pero puedes usar cualquier otro que requieras, por ejemplo, la nomenclatura que
uséis en vuestro proyecto para las historias de usuario).

• Existe un comodín para el campo Active Log User, que con el valor '*' implica todos
los usuarios; recuerda tener cuidado con este valor, dado que no se filtrará ningún
usuario.

• Recuerda que puedes filtrar también por nivel y así minimizar el número de entradas
de log generadas.

18.7.3 Código
El código implementado por el autor se basa en el esquema siguiente:

Ilustración 95 - Esquema de clases


• iLogger: es una interfaz donde se definen los métodos que el usuario del framework podrá
utilizar y que deberás implementar en la clase.

• Logger:es una implementación de iLogger que utiliza la implementación realizada en


LogService.

• LogService: está formada por todos los métodos necesarios para la implementación del
framework, leer los registros de los Custom Metadata, invocar el evento, insertar los
registros que captura el trigger asociado al evento, etc.

Para capturar el Platform Event enviado existe un Trigger que se limita a invocar el método
insertAppLogs de la clase LogService.

Finalmente, te muestro cómo invocar el método WriteLog para utilizar el framework desde Process
Builder, que consiste en invocar el método WriteLog y proporcionar el valor en la variable messages.

114
Frameworks de Logs

Ilustración 96 - Ejemplo de invocación al framework desde Process Builder

18.7.4 Cómo usarlo y resultado obtenido


Para testar el framework te propongo que realices 2 operaciones:

• Ejecuta como código anónimo esta sentencia: LogService.error('Error crítico', 'clase


Principal');

• Te recomiendo que hagas pruebas con las expresiones regulares para comprobar
cómo puedes solucionar casos de uso de sensibilidad de datos.

• Te recomiendo que actives el log solo para ciertos usuarios, y observarás que no
debes modificar el código, solo el registro del Custom Metadata Type.

• Crea un Process Builder como el de la captura anterior sobre el objeto Account y crea una
Account como harías habitualmente.

El resultado obtenido serán las entradas de log en el objeto AppLogs:

Ilustración 97 - Listado de registro del objeto AppLogs

18.7.5 Ventajas e inconvenientes


• (V) Evita las limitaciones del Log de Salesforce, persistiendo la información en un objeto
custom y garantizando así la perdurabilidad de la información, la búsqueda personalizada y
el borrado y/o archivado ad hoc.

• (V) Es un complemento al log de la plataforma y no un sustitutivo, aunque podría llegar a


sustituirlo.

• (V) Mediante el uso de Platform Events se robustece la implementación del framework.

115
La guía definitiva para dominar el Log de Salesforce

• (V) No requiere de conocimientos importantes de programación y puede entenderse


fácilmente.

• (V) Proporciona mecanismos de filtrado, tanto a nivel de datos como a nivel de usuarios,
que pueden ser modificados sin necesidad de modificar el código.

• (V) La documentación existente, tanto en el repositorio de código como el artículo del


autor, es de gran ayuda para entender cómo usar el framework y sus posibilidades.

• (I) Como todos los frameworks que utilizan un objeto custom, el uso de este objeto
impacta en la cantidad de Data Storage consumido.

• (I) El uso de Events requiere de cierto conocimiento, con más código, y analizar cómo las
limitaciones pueden afectar la captura.

Como comentaba al principio, en mi opinión es el framework con la mejor relación entre su curva
de aprendizaje y las capacidades que nos brinda.

Aun así, como te comentaba, lo importante respecto a estos frameworks, además de que se
adecúen mejor o peor a cada uno de tus proyectos, son las ideas que proporcionan para mejorar
tu gestión de log, y crear tu propia versión del framework.

116
Un Framework ideal

19. Un Framework ideal


En mi opinión, los frameworks anteriores proponen soluciones a los problemas más comunes que
encontrarás en un proyecto real. cuando pretendas generar log de manera eficaz.

Pero, habiendo entendido sus capacidades, si te decides a adoptar o a crar un framework, déjame
ayudarte en enumerar cuales son todas aquellas capacidades que deberías considerar. Digo
considerar, porque seguramente no todas ellas te serán necesarias, pero así tomarás una decisión
sobre si abordarlas o descartarlas, y si decides abordarlas, cómo hacerlo.

Por supuesto, dependiendo de las necesidades del proyecto, las capacidades pueden ser variadas
y válidas, por eso mi recomendación es que no te limites a implementar solo lo que necesites
ahora, sino que tengas en cuenta que en un futuro inmediato pueden aparecer nuevas
necesidades y si tomas las decisiones de diseño inapropiadas tengas que rehacer parte del
trabajo.

A continuación, te enumero lo que para mí debiera ofrecer un framework en 2021 para dar
respuesta a la mayoría de los requerimientos habituales (lo sé, no hay 2 proyectos iguales). Verás
que mezclo tanto lo que debe ofrecer como también cómo creo que debe ofrecerlo; supongo que
es una mezcla poco ortodoxa, pero creo que puede ser útil para elegir el framework correcto.

Estas son las características:

1. Debe permitir volcar la información directamente al log de Salesforce o a un objeto custom;


esto debe ser configurable (mediante Custom Metadata Types o Custom Settings).

2. Debe permitir el filtrado de cadenas de texto, y ser configurable. Es decir, el framework debe
ofrecer las capacidades para no mostrar datos sensibles.

3. Debe permitir el filtrado del log, dependiendo del entorno en que esté (muy relacionado con el
punto anterior).

4. Debe proporcionar un mecanismo para, en el caso de uso de DCM (Data Classification


Metadata) ocultar/ofuscar/truncar los valores de los campos en función de su sensibilidad y
tipología especificada por el usuario.

5. Debe permitir la generación de mensajes con un nivel de criticidad, ya sea el de Syslog o el de


otro. Debe, por lo tanto, permitir filtrar los mensajes que aparecen por nivel de criticidad y
configurable*.

6. Debe permitir la notificación a ciertos usuarios en función de un nivel de criticidad del


mensaje, mediante configuración.

7. Debe permitir la generación de logs, sin necesidad de crear Trace Flags, es decir, debe ser
posible generar log sin el mecanismo estándar de Salesforce y siempre mediante
configuración.
Cuando ocurre una incidencia en el entorno de PRO no voy a poder crear un Debug Level, un
Trace Flag, etc.; para averiguar lo que está sucediendo, debería idealmente solicitar cambiar o
modificar un registro de Metadata al administrador y obtener el log.
117
La guía definitiva para dominar el Log de Salesforce

8. Debe permitir la generación de log desde Process Builder y Flow Builder, para así obtener un
log unificado.

9. Debe mostrar información del consumo de límites realizado durante la transacción. Puedes
inspirarte en el patrón de Dan Appleman de push y pop para llevarlo a cabo.

10. Opcionalmente debería tener una política de eliminación o de historificación del log a un
sistema externo o a un Big Object.

11. Opcionalmente debería proporcionar un componente visual que pueda obtener los eventos que
se están generando en tiempo real, para investigar y analizar el log que sucede en un
momento determinado.

Finalmente, enumero aquellas características que me gustaría encontrar en el cómo esté


construido este framework ideal:

1. Debería estar basado en el uso de Platform Events: creo que explico con detalle en la guía las
ventajas e inconvenientes, y para mí son superiores las PROs vs. CONs.

2. Debería estar orientado a interfaces, permitiendo así el intercambio de implementaciones.

3. Debería proporcionar un conjunto de métodos reducido, y mediante la sobrecarga,


aumentarlos para que el usuario del framework no tenga una curva de aprendizaje
pronunciada.

4. Debería estar bien documentado: la metadata utilizada, explicación de los campos y su


implicación en el comportamiento del framework y ejemplos para entender rápidamente cómo
usarlo (no es común encontrar buena documentación con ejemplos actualmente);
desafortunadamente, las clases de test proporcionadas no son habitualmente lo
suficientemente explicativas para entender el comportamiento del framework.

Finalmente, existen otros frameworks disponibles muy interesantes, que seguramente analizaré en
algún momento, pero quiero hacer especial mención de los siguientes:

• Apex Unified Logging de Robert Sosseman44.

• Reliability Force de Johannes Fischer y Kurt Fairfield45, seguramente el framework más


completo y extenso de todos los existentes.

• Salesforce Trigger Actions Framework de Mitchell Spano46, muy interesante y con mucho
énfasis en el contexto de ejecución y las interacciones con la automatización de flujos y
procesos.

44
https://github.com/rsoesemann/apex-unified-logging
45
https://medium.com/ft-product-technology/logging-alerting-and-recovery-on-the-force-com-platform-
67b964aaf29d
46
https://github.com/mitchspano/apex-trigger-actions-framework

118
Apéndices

20. Apéndices
Los siguientes apartados no están estrictamente relacionados con el log de Salesforce, pero creo
que es conocimiento lateral que puede evitarte incidencias durante su gestión y facilitarte el
proceso.

20.1 Gestión de Orgs con la SFDX CLI


Cuando ejecutas un comando en la SDFX CLI que requiere conectarse a una ORG, te recomiendo
que lo hagas de la siguiente manera:

1. Crea un alias para todas las ORGs, ya sean Sandbox, Developer Hubs o Scratchs. Este alias
permite no tener que recordar el username que utilizaste para autorizar la ORG.
Crear un alias es muy sencillo: sfdx force:alias:set ALIAS_QUE_QUIERAS=username@org.com.

Esto convierte un comando como sfdx force:apex:log:list -u estevemain@logs.com en


sfdx force:apex:log:list -u DebHuv, que no parece muy distinto, pero a mí me resulta
mucho más sencillo de recordar y escribir (ni te cuento los usernames que me crean en mi
actual trabajo).

2. Personalmente prefiero no fijar una Org por Default, y esto seguramente molesta sorprende a
la gente. Entonces, ¿por qué lo haces? Pues lo hago para evitar ejecutar comandos en la ORG
equivocada. Desafortunadamente cuando estás trabajando con la SFDX con varias ORG a la
vez, si no especificas el alias de la ORG destino y tienes fijado una ORG por defecto, ese
comando se ejecutará en esa ORG, y si te pasa como a mí, que no es lo deseado, pues...

Aun así, para simplificar todos los comandos de este manual, voy a fijar una ORG por defecto
(DevHub) y así simplificar los comandos para facilitar su comprensión, pero REPITO y que conste
en acta señoría que ni lo recomiendo ni intento hacerlo. Para ello, ejecuto el comando sfdx
force:config:set defaultusername=DevHub o sfdx force:config:set
defaultusername=estevemain@logs.com y obtengo el resultado siguiente:

=== Set Config


Name Value Success
─────────────── ─────────────────── ───────
defaultusername estevemain@logs.com true

20.2 Por qué y cómo usar Postman


Como te comentaba, no tengo ninguna predilección especial para usar Postman respecto a otras
herramientas fantásticas como Paw, SoapUI, Postwoman, etc.

Pero cierto es que el equipo de Salesforce nos proporciona una colección de todas las APIs
implementadas y listas para usar en una colección de Postman47 que es supercómoda y útil.

47
https://github.com/forcedotcom/postman-salesforce-apis

119
La guía definitiva para dominar el Log de Salesforce

Con esta colección de Salesforce, puedes replicar todos los ejemplos de forma muy sencilla, ya
que solo deberás introducir tus datos de conexión, y no deberás preocuparte de toda la fontanería
de creación de la invocación, sabiendo que Salesforce la ha creado y validado.

Una vez instalada Postman, y una vez descargada la colección, ábrela en Postman, crea un nuevo
entorno en la parte superior y complementa los valores necesarios como username, password,
clientId, secretToken, etc.

Ilustración 98 - Configuración del entorno de Postman

Finalmente ejecuta el flujo de autenticación (el más simple es OAuth Username Password) y con la
respuesta se completarán ciertas variables como el token de autenticación, que se usará para el
resto de llamadas que quieras realizar a la API REST, Tooling API, BULK API, etc.

Ilustración 99 - Listado de invocaciones a la API de la colección de Salesforce

La única variable que no informa al realizar la autenticación es {{version}}, por lo que necesitas
fijarla; quizás en tu proyecto habéis acordado el uso de una versión concreta, que puede no ser la última.

A partir de ese momento, puedes realizar las invocaciones APIs contra la Org con la que te hayas
identificado, sin necesidad de bucear en la documentación para construirlas.

20.3 Uso de la librería JQ


Finalmente hay un componente que para mí es muy útil, la librería jq48, y que has visto que he
utilizado durante distintas operaciones.

48
https://shapeshed.com/jq-json/

120
Apéndices

Habitualmente las tareas a realizar con la SFDX CLI requieren encadenar comandos, es decir, que
los resultados del comando anterior son la entrada del siguiente.

Para ello el formato de salida que muchas veces utiliza la CLI, denominado “human”, no es útil,
sino que necesitamos un formato estructurado, idealmente Json.

Para muchos comandos de la CLI, basta con añadir --json para obtener la salida formateada en
ese formato. Pero ¿cómo la utilizamos?

Para utilizar esta respuesta y por ejemplo acceder a un campo determinado, utilizo (y verás que es
una aproximación habitual) la librería jq.

Jq nos permite acceder a los nodos de un documento Json. Veamos un ejemplo, si no todo esto es
muy abstracto:

• El comando sfdx force:apex:log:list proporciona los logs generados en la ORG. Si lo


ejecutamos así sin más, nos devuelve:

Ilustración 100 - Obtención listado de logs mediante CLI


Una salida útil cuando lo que quiero es obtenerlo por pantalla, pero ¿cómo utilizo ese
resultado para obtener los usuarios de la columna LOG USER?

Para ello, lo primero, ejecuta el mismo comando pero solicitando la salida en formato --
json:

Ilustración 101 - Obtención listado de logs mediante CLI en formato Json


Para obtener los nombres de los usuarios, tan solo tenemos que entender cómo está
estructurado, es decir, el campo “Name” tiene como nodos padres result y LogUser. Por lo

121
La guía definitiva para dominar el Log de Salesforce

tanto, si le indicamos a jq que nos proporcione .result[].LogUser.Name, obtenemos


el siguiente resultado:

Ilustración 102 - Resultado de la consulta de los logs a través de pipe con filtro mediante jq para
obtener únicamente el nombre del usuario
Es decir, a la salida del comando sfdx force:apex:log:list --json se lo envías mediante
a jq mediante una pipe para que filtre el array result y que nos devuelva todas las
ocurrencias de Loguser.Name: | jq .result[].LogUser.Name.

Un detalle final, pero útil: la mayoría de las veces debo trabajar con IDs y esas comillas que
aparecen en el nodo me molestan; para eliminarlas, utiliza el parámetro -r:

Ilustración 103 - Resultado de la consulta de logs a través de pipe con filtro mediante jq para
obtener únicamente el nombre del usuario eliminando comillas

122
Enlaces y contenidos interesantes

21. Enlaces y contenidos interesantes


En la siguiente lista te indico enlaces que, sin haber sido incluidos en la guía, creo que es muy
interesante que tengas a mano:

1. Si consideras interesante el uso de un framework de log basado en eventos, te recomiendo


que utilices el Streaming monitor
(https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3A00000FYEEWUA5),
de Philippe Ozil (Principal Developer Advocate de Salesforce), que permite suscribirse y
visualizar los eventos generados de una manera muy práctica, evitando que tengas que crear
un componente adicional.

2. Curso de Pluralsight - Play by Play: Everything You Always Wanted to Know About Salesforce
Logs but Were Afraid to Ask de Don Robins y Christian Knapp
(https://app.pluralsight.com/library/courses/play-by-play-everything-you-wanted-know-about-
salesforce-logs-afraid-to-ask/table-of-contents).

3. Vídeo de Codelive: Log You Some Events for Great Good


(https://trailhead.salesforce.com/live/videos/a2r3k000001n2Ba/codelive---log-you-some-
events-for-great-good).

4. Vídeo y artículo de Andrew Fawcett: Advanced Logging with Platform Events de Andrew Fawcett
con referencia a 2 videos de Dreamforce y Apex Process Orchestration and Monitoring with
Platform Events de Andrew Fawcett (https://github.com/afawcett/eventlogging).

5. Artículo de Salesforce Architects con un listado de herramientas interesantes no solo para Log
sino para evaluación de rendimiento en general: Diagnostics and Monitoring Tools for
Salesforce — Part 1 (https://medium.com/salesforce-architects/diagnostics-and-monitoring-
tools-for-salesforce-part-1-bfa059f9a63e).

6. Trailhead sobre el Apex Reply Debugger: Find and Fix Bugs with Apex Replay Debugger
(https://trailhead.salesforce.com/content/learn/projects/find-and-fix-bugs-with-apex-replay-
debugger).

7. Artículo de Gareth Park: Logging, Alerting and Recovery on the Force.com Platform
(https://medium.com/ft-product-technology/logging-alerting-and-recovery-on-the-force-com-
platform-67b964aaf29d) .

8. Artículo de Simon Goodyear: How to Use Loggly in Apex for Massive Scale Logging
(https://es.slideshare.net/developerforce/loggly).

9. La extensión para navegador LogMachine, que facilita la lectura del log y proporciona ciertas
características atrayentes: LogMachine
(https://chrome.google.com/webstore/detail/logmachine/ngppecjgpbgmfcjjakdjfbnpnihcgpdb?
hl=en-US).

10. Spexy es una herramienta para la visualización de logs muy atractiva, y aunque requiere de
conocimientos técnicos avanzados para usarla, te recomiendo que la pruebes, ya que organiza

123
La guía definitiva para dominar el Log de Salesforce

la información de una manera muy interesante: repositorio de Spexy


(https://github.com/mgangadhar/spexy); creo que Salesforce podría incorporar varias de sus
ideas.

124
Agradecimientos

22. Agradecimientos
Quiero agradecerte a ti que estás leyendo este libro, haber dedicado tu tiempo y espero que haya
valido la pena. Me encantaría recibir tu opinión, puedes contactarme a través del Linkedin.

Quiero dar las gracias especialmente a David Sánchez Carmona49 (@animuscrm), que fue el primer
lector completo de este libro, y sin cuyo feedback y tiempo personal este libro sería francamente
peor.

Agradecer a Pablo García50 (@pablo8374), su lectura y feedback del texto y la ayuda a promocionar
el libro entre nuestros compañeros de comunidad.

Quiero agradecer a mi amigo Albert Soler su corrección del texto, las decenas de sugerencias y
comentarios; sin su ayuda esta guía no sería legible.

Quiero dar las gracias a mis amigos Juan Pablo y Yago, que invirtieron tiempo en darme feedback
para mejorar esta guía, especialmente en su estructura y formato.

Quiero dar las gracias a todos aquellos compañeros/as que he encontrado en diferentes proyectos
que me han enseñado y de los que he aprendido un montón, y de los que sigo aprendiendo
diariamente, confirmándome todo lo que me falta por saber.

Quiero daros las gracias a todos los que publicáis y compartís vuestro conocimiento; sin vosotros
nunca habría podido crear esta guía ni otros contenidos.

Quiero agradecer a Unsplash51, y en este caso Gerrie Van der Walt52, que proporcione imágenes
espectaculares que otros usuarios podamos usar (la de la portada es una de ellas).

Esta guía utiliza las fuentes Atkinson Hiperlegible53 del Instituto Braille e IBM Plex Mono54, de
IBM, para mejorar la lectura y la comprensión de personas con visión disminuida, aunque solo
están disponibles en formatos ebook. Agradezco a ambos proyectos cederlas para su uso.

Esta guía ha obtenido un nivel de comprensión de 61.68 en el test INFLESZ (dificultad de los
textos mediante la fórmula de perspicuidad de Flesch-Szigriszt), indicando un nivel de dificultad
lectora de “normal”. Agradezco a legible.es por facilitar la herramienta para calcularlo.

La frase “En teoría, no hay diferencia entre teoría y práctica. Pero en la práctica, sí que la hay” se
atribuye a Jan L.A. Van de Snepscheut.

49
https://linkedin.com/in/davidsanchezcarmonabegur
50
https://www.linkedin.com/in/pablogarciapulgarin
51
https://unsplash.com/
52
https://unsplash.com/@gitfo
53
https://brailleinstitute.org/wp-content/uploads/2020/02/BIA_AtkinsonHyerlegible-Specimen_200210.pdf
54
https://fonts.google.com/specimen/IBM+Plex+Mono

125
La guía definitiva para dominar el Log de Salesforce

23. Garantía
He dedicado muchas horas a elaborar y revisar el contenido de esta guía, pero seguro que se
habrán escapado algunos errores, por lo que no existe garantía de que tanto mi código como el de
los autores que menciono no contengan errores u omisiones. No puedo asumir ninguna
responsabilidad por el uso total o parcial de los contenidos de esta guía ni por los daños que se
puedan ocasionar.

Te agradecería muchísimo que, si encuentras un error o incluso aprecias que no se entiende


correctamente algún apartado, me escribas (ya te lo agradezco de antemano):
librolog@onmail.com.

Las opiniones expresadas en esta guía son completamente personales y pueden no coincidir con
mi actual empleador o anteriores, con las de Salesforce, o las de cualquier otro colectivo o
empresa cualificada; son mis opiniones basadas en mis experiencias, nada más.

Salesforce.com, Force.com, Ligthning, VisualForce, Apex y ApexExchange son marcas registradas


por Salesforce.com.

¿Quieres saber algo más sobre mí? Accede a mi blog, donde encontrarás todos mis artículos
publicados, así como un poco de mi biografía: https://forcegraells.com.

126
Cambios entre versiones

24. Cambios entre versiones


• Versión Mayo 2021: he renombrado el apartado Conclusiones sobre Frameworks,
para llamarse Un Framework ideal y he añadido como criterio que el framework
tenga en consideración el uso de DCM.
• Versión Diciembre 2022: se han eliminado emoticonos y otros componentes visuales
que no aparecen impresos correctamente en Amazon Publishing. Además, se han
formateado partes del texto de forma distinta para disminuir el número de páginas.
Se ha eliminado Wave como Categoría.

127

También podría gustarte