(Quick Reference)

3.1.2 Logging - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith

Version: null

3.1.2 Logging

The Basics

Grails uses its common configuration mechanism to provide the settings for the underlying Log4j log system, so all you have to do is add a log4j setting to the file grails-app/conf/Config.groovy.

So what does this log4j setting look like? Here's a basic example:

Los conceptos básicos

Grails utiliza su mecanismo de configuración para proporcionar la configuración base para el sistema de logs Log4j por lo que todo lo que tiene que hacer es agregar la configuración para log4j al archivo grails-app/conf/Config.groovy

Así que ¿cómo es la configuración para este log4j? Aquí tiene un ejemplo básico:

log4j = {
    error  'org.codehaus.groovy.grails.web.servlet',  //  controllers
           'org.codehaus.groovy.grails.web.pages' //  GSP

warn 'org.apache.catalina' }

This says that for loggers whose name starts with 'org.codehaus.groovy.grails.web.servlet' or 'org.codehaus.groovy.grails.web.pages', only messages logged at 'error' level and above will be shown. Loggers with names starting with 'org.apache.catalina' logger only show messages at the 'warn' level and above. What does that mean? First of all, you have to understand how levels work.

Logging levels

The are several standard logging levels, which are listed here in order of descending priority:

  1. off
  2. fatal
  3. error
  4. warn
  5. info
  6. debug
  7. trace
  8. all

When you log a message, you implicitly give that message a level. For example, the method log.error(msg) will log a message at the 'error' level. Likewise, log.debug(msg) will log it at 'debug'. Each of the above levels apart from 'off' and 'all' have a corresponding log method of the same name.

The logging system uses that message level combined with the configuration for the logger (see next section) to determine whether the message gets written out. For example, if you have an 'org.example.domain' logger configured like so:

Esto dice que para los loggers cuyo nombre comienza con 'org.codehaus.groovy.grails.web.servlet' o 'org.codehaus.groovy.grails.web.pages', sólo se registran mensajes a nivel de 'error' y superiores. Los loggers con nombres que empiezan con 'org.apache.catalina' sólo resgistran mensajes de nivel 'warn' y superiores. ¿Qué significa eso? En primer lugar, hay que entender cómo funcionan los niveles.

Niveles de registro

Existen varios niveles de registro estándar, que se listan en orden descendente de prioridad:

  1. off
  2. fatal
  3. error
  4. warn
  5. info
  6. debug
  7. trace
  8. all

Cuando resgistras un mensaje, implícitamente se le da a ese mensaje de un nivel. Por ejemplo, el método log.error(msg) registrará un mensaje en el nivel de "error". Asimismo, log.debug(msg) se registrará en 'debug'. Cada uno de los niveles anteriores aparte de 'off' y 'all' tienen un método de registro correspondiente con el mismo nombre.

El sistema de registro utiliza el nivel del mensaje combinado con la configuración para el logger (consulte la siguiente sección) para determinar si se escribe el mensaje. Por ejemplo, si tienes un logger de 'org.example.domain' configurado así:

warn 'org.example.domain'

then messages with a level of 'warn', 'error', or 'fatal' will be written out. Messages at other levels will be ignored.

Before we go on to loggers, a quick note about those 'off' and 'all' levels. These are special in that they can only be used in the configuration; you can't log messages at these levels. So if you configure a logger with a level of 'off', then no messages will be written out. A level of 'all' means that you will see all messages. Simple.

luego se escribirán los mensajes con un nivel de 'warn', 'error' o 'fatal'. Se omitirán los mensajes a otros niveles.

Antes de continuar con los loggers, una nota rápida sobre los nivels 'off' y 'all'. Estos son especiales ya que sólo pueden utilizarse en la configuración; no se puede registrar los mensajes en estos niveles. Así que si configura un registrador con un nivel de 'off', ningún mensaje se escribirá. Un nivel de 'all' significa que se verán todos los mensajes. Simple.

Loggers

Loggers are fundamental to the logging system, but they are a source of some confusion. For a start, what are they? Are they shared? How do you configure them?

A logger is the object you log messages to, so in the call log.debug(msg), log is a logger instance (of type Log). These loggers are cached and uniquely identified by name, so if two separate classes use loggers with the same name, those loggers are actually the same instance.

There are two main ways to get hold of a logger:

  1. use the log instance injected into artifacts such as domain classes, controllers and services;
  2. use the Commons Logging API directly.

If you use the dynamic log property, then the name of the logger is 'grails.app.<type>.<className>', where type is the type of the artifact, for example 'controller' or 'service, and className is the fully qualified name of the artifact. For example, if you have this service:

Loggers

Los loggers son fundamentales para el sistema de log, pero son una fuente de confusión. Para empezar, ¿qué son? ¿son compartidos? ¿cómo configurarlos?

Un logger es el objeto en el que registras mensajes, por lo que en la llamada log.debug(msg), log es una instancia de logger (del tipo Log). Estos loggers se almacenan en caché y se identifica por su nombre, por lo que si dos clases distintas utilizan dos loggers con el mismo nombre, los loggers son realmente la misma instancia.

Hay dos formas principales de apoderarse de un registrador:

  1. Usar la instancia de log que se inyecta en los artefactos, como las clases de dominio, los controladores y servicios;
  2. Utilizar la API de Commons Logging directamente.

Si se utiliza la propiedad dinámica log, entonces el nombre del log es "grails.app.<tipo>. <nombreClase> ', Donde tipo es el tipo de artefacto, por ejemplo 'controlador' o 'servicio" y nombreClase es el nombre completo del artefacto. Por ejemplo, si usted tiene este servicio:

package org.example

class MyService { … }

then the name of the logger will be 'grails.app.services.org.example.MyService'.

For other classes, the typical approach is to store a logger based on the class name in a constant static field:

el nombre del logger será 'grails.app.services.org.example.MyService'.

Para otras clases, el enfoque típico es almacenar un logger basado en el nombre de clase en un campo estático constante:

package org.other

import org.apache.commons.logging.LogFactory

class MyClass { private static final log = LogFactory.getLog(this) … }

This will create a logger with the name 'org.other.MyClass' - note the lack of a 'grails.app.' prefix since the class isn't an artifact. You can also pass a name to the getLog() method, such as "myLogger", but this is less common because the logging system treats names with dots ('.') in a special way.

Configuring loggers

You have already seen how to configure loggers in Grails:

Esto creará un logger con el nombre 'org.other.MyClass' - nota la falta de un prefijo 'grails.app.' ya que la clase no es un artefacto. También se puede pasar un nombre al método getLog(), como "myLogger", pero esto es menos común porque el sistema de registro trata los nombres con puntos ('. ') de una manera especial.

Configuración de los loggers

Ya has visto cómo configurar los loggers en Grails:

log4j = {
    error  'org.codehaus.groovy.grails.web.servlet'
}

This example configures loggers with names starting with 'org.codehaus.groovy.grails.web.servlet' to ignore any messages sent to them at a level of 'warn' or lower. But is there a logger with this name in the application? No. So why have a configuration for it? Because the above rule applies to any logger whose name begins with 'org.codehaus.groovy.grails.servlet.' as well. For example, the rule applies to both the org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet class and the org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest one.

In other words, loggers are hierarchical. This makes configuring them by package much simpler than it would otherwise be.

The most common things that you will want to capture log output from are your controllers, services, and other artifacts. Use the convention mentioned earlier to do that: grails.app.<artifactType>.<className> . In particular the class name must be fully qualifed, i.e. with the package if there is one:

Este ejemplo configura los loggers con nombres que empiecen por 'org.codehaus.groovy.grails.web.servlet' para ignorar cualquier mensaje enviado a ellos a un nivel de 'warn' o inferior. ¿Pero hay un logger con este nombre en la aplicación? No. Así que ¿por qué tiene una configuración para ello? Debido a la regla anterior aplica a cualquier logger cuyo nombre empiece con 'org.codehaus.groovy.grails.servlet.' así, por ejemplo, la regla se aplica a la clase org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet y a org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest.

En otras palabras, los loggers son jerárquicos. Esto hace que configurarlos por paquete mucho más simple de lo que sería de otra manera.

Las cosas más comunes que desea capturar el registro de salida son los controladores, servicios y otros artefactos. Utilice la convención mencionada anteriormente para ello: grails.app.<tipoArtefacto>.<nombreClase> . En particular el nombre de clase debe ser plenamente cualificado, es decir, con el paquete si hay uno:

log4j = {
	    // Establece el nivel de todos los artefactos de aplicación
	    info "grails.app"

// Establece el nivel para un controlador específico en un paquete predeterminado debug "grails.app.controllers.YourController"

// Establece el nivel para una clase de dominio específico debug "grails.app.domain.org.example.Book"

// Establecer el nivel para todos taglibs info "grails.app.taglib" }

The standard artifact names used in the logging configuration are:

  • conf - For anything under grails-app/conf such as BootStrap.groovy and filters
  • taglib - For tag libraries
  • services - For service classes
  • controllers - For controllers
  • domain - For domain entities

Grails itself generates plenty of logging information and it can sometimes be helpful to see that. Here are some useful loggers from Grails internals that you can use, especially when tracking down problems with your application:

Los nombres de artefacto estándar utilizados en la configuración de log son:

  • conf - para cualquier cosa bajo grails-app/conf como el BootStrap.groovy y filtros.
  • taglib - para las bibliotecas de etiquetas.
  • servicios - para las clases de servicio.
  • controllers - Para los controladores.
  • domain - para entidades de dominio

Grails en sí genera un montón de información de registro y a veces puede ser útil verla. A continuación presentamos algunos loggers internos útiles de Grails que puede utilizar, especialmente al intentar solucionar problemas con la aplicación:

  • org.codehaus.groovy.grails.commons - Core artifact information such as class loading etc.
  • org.codehaus.groovy.grails.web - Grails web request processing
  • org.codehaus.groovy.grails.web.mapping - URL mapping debugging
  • org.codehaus.groovy.grails.plugins - Log plugin activity
  • grails.spring - See what Spring beans Grails and plugins are defining
  • org.springframework - See what Spring is doing
  • org.hibernate - See what Hibernate is doing

So far, we've only looked at explicit configuration of loggers. But what about all those loggers that don't have an explicit configuration? Are they simply ignored? The answer lies with the root logger.

  • org.codehaus.groovy.grails.commons - información del núcleo como carga de clases etc..
  • org.codehaus.groovy.grails.web - Procesamiento de solicitudes web de Grails.
  • org.codehaus.groovy.grails.web.mapping - Depuración de mapeo de URLs.
  • org.codehaus.groovy.grails.plugins - registro de actividad de plugins.
  • grails.spring - ver qué hace beans de Spring y plugins Grails estan definidos.
  • org.springframework - ver qué hace Spring.
  • org.hibernate - ver lo que está haciendo ibernate.

Hasta ahora, sólo hemos mirado de configuración explícita de los loggers. Pero ¿qué pasa con todos los registradores que no tienen una configuración explícita? ¿Son simplemente ignorados? La respuesta se encuentra con el logger raiz.

The Root Logger

All logger objects inherit their configuration from the root logger, so if no explicit configuration is provided for a given logger, then any messages that go to that logger are subject to the rules defined for the root logger. In other words, the root logger provides the default configuration for the logging system.

Grails automatically configures the root logger to only handle messages at 'error' level and above, and all the messages are directed to the console (stdout for those with a C background). You can customise this behaviour by specifying a 'root' section in your logging configuration like so:

El registrador raíz

Todos los registradores heredarán su configuración del logger raíz, por lo que si no se proporciona ninguna configuración explícita para un logger determinado y así todos los mensajes que llegan a ese registrador están sujetos a las reglas definidas para el logger raíz. En otras palabras, el logger raíz proporciona la configuración predeterminada para el sistema de log.

Grails configura automáticamente el logger raíz para sólo gestionar los mensajes "error" y superiores, y todos los mensajes se dirigen a la consola (stdout para aquellos con un pasado con C). Puede personalizar este comportamiento especificando una sección de 'root' en la configuración del log de este modo:

log4j = {
    root {
        info()
    }
    …
}

The above example configures the root logger to log messages at 'info' level and above to the default console appender. You can also configure the root logger to log to one or more named appenders (which we'll talk more about shortly):

En el ejemplo anterior se configura el logger raíz para registrar mensajes a nivel de 'info' y por encima en el appender de consola predeterminada. También puede configurar el logger raíz para registrar a uno o más appenders con nombre (sobre lo que ya hablaremos más en breve):

log4j = {
    appenders {
        file name:'file', file:'/var/logs/mylog.log'
    }
    root {
        debug 'stdout', 'file'
    }
}

In the above example, the root logger will log to two appenders - the default 'stdout' (console) appender and a custom 'file' appender.

For power users there is an alternative syntax for configuring the root logger: the root org.apache.log4j.Logger instance is passed as an argument to the log4j closure. This lets you work with the logger directly:

En el ejemplo anterior, el registrador raíz registrará a dos appenders, el appender predeterminada 'debug' (consola) y un appender personalizado 'file'.

Para usuarios avanzados existe una sintaxis alternativa para configurar el logger raíz: la instancia de logger raiz org.apache.log4j.Logger se pasa como un argumento a la closure de log4j. Esto le permite trabajar directamente con el logger:

log4j = { root ->
    root.level = org.apache.log4j.Level.DEBUG
    …
}

For more information on what you can do with this Logger instance, refer to the Log4j API documentation.

Those are the basics of logging pretty well covered and they are sufficient if you're happy to only send log messages to the console. But what if you want to send them to a file? How do you make sure that messages from a particular logger go to a file but not the console? These questions and more will be answered as we look into appenders.

Appenders

Loggers are a useful mechanism for filtering messages, but they don't physically write the messages anywhere. That's the job of the appender, of which there are various types. For example, there is the default one that writes messages to the console, another that writes them to a file, and several others. You can even create your own appender implementations!

This diagram shows how they fit into the logging pipeline:

Para obtener más información sobre lo que puede hacer con esta instancia de Logger, consulte la documentación de la API de Log4j.

Esos son los elementos básicos de registro bastante bien cubiertos y son suficientes si sólo quieres enviar mensajes de log a la consola. Pero ¿qué sucede si desea registrar en un archivo? ¿Cómo asegurarnos de que los mensajes de un logger particular vayan a un archivo, pero no a la consola? Se responderá estas preguntas y más revisando los appenders.

Appenders

Los loggers son un mecanismo útil para el filtrado de mensajes, pero físicamente no escriben los mensajes en ningún sitio. Esto es trabajo del appender, de los cuales hay varios tipos. Por ejemplo, el appender por defecto escribe los mensajes de la consola, existe otro que escribe en un archivo y algunos otros. ¡Incluso puede crear su propia implementación!

Este diagrama muestra cómo encajan en el flujo de registro:

As you can see, a single logger may have several appenders attached to it. In a standard Grails configuration, the console appender named 'stdout' is attached to all loggers through the default root logger configuration. But that's the only one. Adding more appenders can be done within an 'appenders' block:

Como puede ver, un logger puede tener varios appenders conectados a él. En una configuración estándar de Grails, el appender de consola denominada 'debug' está unido a todos los logger mediante la configuración predeterminada del logger raíz. Pero es el único. Agregar más appenders puede hacerse dentro de un bloque de 'appenders':

log4j = {
    appenders {
        rollingFile name: "myAppender",
                    maxFileSize: 1024,
                    file: "/tmp/logs/myApp.log"
    }
}

The following appenders are available by default:

NameClassDescription
jdbcJDBCAppenderLogs to a JDBC connection.
consoleConsoleAppenderLogs to the console.
fileFileAppenderLogs to a single file.
rollingFileRollingFileAppenderLogs to rolling files, for example a new file each day.

Las siguientes appenders están disponibles de forma predeterminada:

NombreClaseDescripción
jdbcJDBCAppenderRegistra a una conexión JDBC.
consolaConsoleAppenderRegistra en la consola.
fileFileAppenderRegistra a un archivo.
rollingFileRollingFileAppenderRegistra a varios archivos, por ejemplo un archivo nuevo cada día.

Each named argument passed to an appender maps to a property of the underlying Appender implementation. So the previous example sets the name, maxFileSize and file properties of the RollingFileAppender instance.

You can have as many appenders as you like - just make sure that they all have unique names. You can even have multiple instances of the same appender type, for example several file appenders that log to different files.

If you prefer to create the appender programmatically or if you want to use an appender implementation that's not available in the above syntax, simply declare an appender entry with an instance of the appender you want:

Cada argumento con nombre pasado a un appender se asigna a una propiedad de la implementación subyacente del Appender. Así que el ejemplo anterior establece las propiedades nombre, maxFileSize y file de la instancia de RollingFileAppender.

Puede tener tantos appenders como quiera, solo asegúrese que todos tienen nombres únicos. Incluso puede tener varias instancias del mismo tipo appender, por ejemplo de varios appenders file que registran en archivos diferentes.

Si prefiere crear el appender mediante programación o si desea utilizar una implementación de appender que no está disponible en la sintaxis anterior, simplemente declarar una entrada appender con la instancia del appender que desee:

import org.apache.log4j.*

log4j = { appenders { appender new RollingFileAppender( name: "myAppender", maxFileSize: 1024, file: "/tmp/logs/myApp.log") } }

This approach can be used to configure JMSAppender, SocketAppender, SMTPAppender, and more.

Once you have declared your extra appenders, you can attach them to specific loggers by passing the name as a key to one of the log level methods from the previous section:

error myAppender: "grails.app.controllers.BookController"

This will ensure that the 'grails.app.controllers.BookController' logger sends log messages to 'myAppender' as well as any appenders configured for the root logger. To add more than one appender to the logger, then add them to the same level declaration:

Este enfoque puede utilizarse para configurar JMSAppender, SocketAppender, SMTPAppender y muchos más.

Una vez que ha declarado sus appenders adicionales, puede conectarlos a loggers específicos pasando el nombre como clave a uno de los métodos de registro de niveles de la sección anterior:

error myAppender: "grails.app.controllers.BookController"

Esto asegurará que el logger de 'grails.app.controllers.BookController' envía mensajes de registro a 'myAppender', así como cualquier appender configurado para el logger raíz. Para agregar más de un appender al logger agreguelos a la misma declaración de nivel:

error myAppender:      "grails.app.controllers.BookController",
      myFileAppender:  ["grails.app.controllers.BookController",
                        "grails.app.services.BookService"],
      rollingFile:     "grails.app.controllers.BookController"

The above example also shows how you can configure more than one logger at a time for a given appender (myFileAppender) by using a list.

El ejemplo anterior muestra cómo puede configurar más de un logger para un determinado appender (myFileAppender) usando una lista.

Be aware that you can only configure a single level for a logger, so if you tried this code:

error myAppender:      "grails.app.controllers.BookController"
debug myFileAppender:  "grails.app.controllers.BookController"
fatal rollingFile:     "grails.app.controllers.BookController"

you'd find that only 'fatal' level messages get logged for 'grails.app.controllers.BookController'. That's because the last level declared for a given logger wins. What you probably want to do is limit what level of messages an appender writes.

Tenga en cuenta que sólo se puede configurar un único nivel de un logger, así que si has probado este código:

error myAppender:      "grails.app.controllers.BookController"
debug myFileAppender:  "grails.app.controllers.BookController"
fatal rollingFile:     "grails.app.controllers.BookController"

encontrará que se registran los mensajes de niveles sólo 'fatal' para 'grails.app.controllers.BookController'. Eso es porque el último nivel declarado para un logger dado es el que se asigna. Lo que probablemente desea hacer es limitar el nivel de mensajes que un appender escribe.

An appender that is attached to a logger configured with the 'all' level will generate a lot of logging information. That may be fine in a file, but it makes working at the console difficult. So we configure the console appender to only write out messages at 'info' level or above:

Un appender que está conectada a un logger configurado con el nivel 'all' va a generar una gran cantidad de información de registro. Esto puede estar bien en un archivo, pero hace difícil trabajar en la consola. Así que configuramos el appender consola sólo para escribir mensajes a nivel de 'info' o superior:

log4j = {
    appenders {
        console name: "stdout", threshold: org.apache.log4j.Level.INFO
    }
}

The key here is the threshold argument which determines the cut-off for log messages. This argument is available for all appenders, but do note that you currently have to specify a Level instance - a string such as "info" will not work.

Custom Layouts

By default the Log4j DSL assumes that you want to use a PatternLayout. However, there are other layouts available including:

  • xml - Create an XML log file
  • html - Creates an HTML log file
  • simple - A simple textual log
  • pattern - A Pattern layout

La clave aquí es el argumento threshold que determina el límite de mensajes de log. Este argumento está disponible para todos los appenders, pero tenga en cuenta que actualmente tiene que especificar una instancia Level, una cadena como "info" no funcionará.

Esquemas personalizados

De forma predeterminada el DSL asume que desea utilizar PatternLayout. Sin embargo, hay otros esquemas disponibles incluyendo:

  • xml - crear un archivo de log XML
  • html - crea un archivo de log HTML
  • simple - un simple log textual
  • patrón - diseño de un esquema

You can specify custom patterns to an appender using the layout setting:

Puede especificar esquemas personalizados para un appender mediante el parámetro layout:

log4j = {
    appenders {
        console name: "customAppender",
                layout: pattern(conversionPattern: "%c{2} %m%n")
    }
}

This also works for the built-in appender "stdout", which logs to the console:

Esto también funciona para el appender incorporado "debug", que inicia una sesión en la consola:

log4j = {
    appenders {
        console name: "stdout",
                layout: pattern(conversionPattern: "%c{2} %m%n")
    }
}

Environment-specific configuration

Since the logging configuration is inside Config.groovy, you can put it inside an environment-specific block. However, there is a problem with this approach: you have to provide the full logging configuration each time you define the log4j setting. In other words, you cannot selectively override parts of the configuration - it's all or nothing.

To get around this, the logging DSL provides its own environment blocks that you can put anywhere in the configuration:

Configuración específica para el entorno

Desde que la configuración de registro está dentro de Config.groovy, puede colocarlo dentro de un bloque específico de entorno. Sin embargo, hay un problema con este enfoque: tiene que proporcionar la configuración de registro completa cada vez que se defina la configuración log4j. En otras palabras, no se puede anular de manera selectiva elementos de la configuración, es todo o nada.

Para evitar esto, el DSL de log proporciona sus propios bloques de entorno que puede colocar en cualquier parte de la configuración:

log4j = {
    appenders {
        console name: "stdout",
                layout: pattern(conversionPattern: "%c{2} %m%n")

environments { production { rollingFile name: "myAppender", maxFileSize: 1024, file: "/tmp/logs/myApp.log" } } }

root { //… }

// other shared config info "grails.app.controller"

environments { production { // Override previous setting for 'grails.app.controller' error "grails.app.controller" } } }

The one place you can't put an environment block is inside the root definition, but you can put the root definition inside an environment block.

Full stacktraces

When exceptions occur, there can be an awful lot of noise in the stacktrace from Java and Groovy internals. Grails filters these typically irrelevant details and restricts traces to non-core Grails/Groovy class packages.

When this happens, the full trace is always logged to the StackTrace logger, which by default writes its output to a file called stacktrace.log. As with other loggers though, you can change its behaviour in the configuration. For example if you prefer full stack traces to go to the console, add this entry:

El lugar no se puede poner un bloque de entorno es dento la definición root, pero puede poner la definición root dentro de un bloque de entorno.

Stacktraces completa

Cuando se producen excepciones, puede haber mucho ruido en el stacktrace de Java y Groovy. Grails filtra estos detalles típicamente irrelevantes y restringe la traza a paquetes de clase Groovy/Grails complementarios.

Cuando esto sucede, la traza completa siempre se registra para el logger StackTrace, que, por defecto, escribe su salida a un archivo denominado stacktrace.log. Como con otros loggers, puede cambiar su comportamiento en la configuración. Por ejemplo, si prefiere que estas trazasvayan a la consola, puede agregar esta entrada:

error stdout: "StackTrace"

This won't stop Grails from attempting to create the stacktrace.log file - it just redirects where stack traces are written to. An alternative approach is to change the location of the 'stacktrace' appender's file:

Esto no impedirá que Grails intente crear el archivo stacktrace.log, simplemente redirige donde se escriben trazas. Un método alternativo es cambiar la ubicación del archivo del appender 'stacktrace':

log4j = {
    appenders {
        rollingFile name: "stacktrace", maxFileSize: 1024,
                    file: "/var/tmp/logs/myApp-stacktrace.log"
    }
}

or, if you don't want to the 'stacktrace' appender at all, configure it as a 'null' appender:

o, si no desea el appender 'stacktrace', puede configurarlo como un appender 'null':

log4j = {
    appenders {
        'null' name: "stacktrace"
    }
}

You can of course combine this with attaching the 'stdout' appender to the 'StackTrace' logger if you want all the output in the console.

Finally, you can completely disable stacktrace filtering by setting the grails.full.stacktrace VM property to true:

grails -Dgrails.full.stacktrace=true run-app

Por supuesto puede combinarlo con anexar el appender 'stdout' al logger 'StackTrace' si desea toda la salida de la consola.

Por último, puede deshabilitar completamente el filtrado stacktrace estableciendo la propiedad VM grails.full.stacktrace a true:

grails -Dgrails.full.stacktrace=true run-app

Masking Request Parameters From Stacktrace Logs

When Grails logs a stacktrace, the log message may include the names and values of all of the request parameters for the current request. To mask out the values of secure request parameters, specify the parameter names in the grails.exceptionresolver.params.exclude config property:

grails.exceptionresolver.params.exclude = ['password', 'creditCard']

Request parameter logging may be turned off altogether by setting the grails.exceptionresolver.logRequestParameters config property to false. The default value is true when the application is running in DEVELOPMENT mode and false for all other modes.

grails.exceptionresolver.logRequestParameters=false

Enmascaramiento de parámetros de request de registros Stacktrace

Cuando Grails registra una stacktrace, el mensaje de log puede incluir los nombres y valores de todos los parámetros de la petición de la request actual. Para ocultar los valores de parámetros de request segura, especifique los nombres de parámetro en la propiedad de configuración grails.exceptionresolver.params.exclude:

grails.exceptionresolver.params.exclude = ['password', 'creditCard']

El registro de parámetros puede desactivarse totalmente estableciendo la propiedad de configuración grails.exceptionresolver.logRequestParameters a false. El valor predeterminado es true cuando la aplicación se ejecuta en modo de desarrollo y false para todos los demás modos.

Grails.exceptionresolver.logRequestParameters=false

Logger inheritance

Earlier, we mentioned that all loggers inherit from the root logger and that loggers are hierarchical based on '.'-separated terms. What this means is that unless you override a parent setting, a logger retains the level and the appenders configured for that parent. So with this configuration:

Herencia de logger

Anteriormente, se mencionó que todos los registradores heredarán del logger raíz y que los registradores son jerárquicos basados en el separador '.'. Esto significa que a menos que reemplace a un padre, un logger mantiene el nivel y las appenders configurados para ese padre. Por lo tanto con esta configuración:

log4j = {
    appenders {
        file name:'file', file:'/var/logs/mylog.log'
    }
    root {
        debug 'stdout', 'file'
    }
}

all loggers in the application will have a level of 'debug' and will log to both the 'stdout' and 'file' appenders. What if you only want to log to 'stdout' for a particular logger? Change the 'additivity' for a logger in that case.

Additivity simply determines whether a logger inherits the configuration from its parent. If additivity is false, then its not inherited. The default for all loggers is true, i.e. they inherit the configuration. So how do you change this setting? Here's an example:

todos los loggers en la aplicación tendrán un nivel de 'debug' y registrarán a los appenders 'stdout' y 'file'. ¿Y si sólo desea registrar a 'stdout' para un registrador particular? Cambie el 'additivity' para un logger en ese caso.

'Additivity' simplemente determina si un registrador hereda la configuración de su padre. Si 'additivity' es falso, entonces es no heredado. El valor predeterminado para todos los registradores es cierto, es decir, heredan la configuración. Entonces, ¿cómo se cambia esta configuración? Aquí está un ejemplo:

log4j = {
    appenders {
        …
    }
    root {
        …
    }

info additivity: false stdout: ["grails.app.controllers.BookController", "grails.app.services.BookService"] }

So when you specify a log level, add an 'additivity' named argument. Note that you when you specify the additivity, you must configure the loggers for a named appender. The following syntax will not work:

info additivity: false, ["grails.app.controllers.BookController",
                         "grails.app.services.BookService"]

Customizing stack trace printing and filtering

Así que cuando se especifica un nivel de registro, agregue un argumento 'additivity'. Tenga en cuenta que cuando se especifica la 'additivity', debe configurar los loggers para un appender con nombre. La siguiente sintaxis no funcionará:

info additivity: false, ["grails.app.controllers.BookController",
                         "grails.app.services.BookService"]

Personalización de impresión y filtro de stacktraces

Stacktraces in general and those generated when using Groovy in particular are quite verbose and contain many stack frames that aren't interesting when diagnosing problems. So Grails uses a implementation of the org.codehaus.groovy.grails.exceptions.StackTraceFilterer interface to filter out irrelevant stack frames. To customize the approach used for filtering, implement that interface in a class in src/groovy or src/java and register it in Config.groovy:

grails.logging.stackTraceFiltererClass =
         'com.yourcompany.yourapp.MyStackTraceFilterer'

In addition, Grails customizes the display of the filtered stacktrace to make the information more readable. To customize this, implement the org.codehaus.groovy.grails.exceptions.StackTracePrinter interface in a class in src/groovy or src/java and register it in Config.groovy:

Las tacktraces en general y aquellas generadas al usar Groovy en particular son bastante detallados y contienen muchos líneas que no son interesantes al diagnosticar problemas. Así Grails utiliza una implementación de la interfaz org.codehaus.groovy.grails.exceptions.StackTraceFilterer para filtrar las líneas irrelevantes. Para personalizar el enfoque utilizado para filtrar, puede implementar esta interfaz en una clase en src/groovy o src/java y registrarlo en Config.groovy:

grails.logging.stackTraceFiltererClass =
         'com.yourcompany.yourapp.MyStackTraceFilterer'

Además, Grails personaliza la presentación de la stacktrace filtrada para hacer que la información sea más legible. Para personalizar este, puede implementar la interfaz org.codehaus.groovy.grails.exceptions.StackTracePrinter en una clase en src/groovy o src/java y registrarlo en Config.groovy:

grails.logging.stackTracePrinterClass =
         'com.yourcompany.yourapp.MyStackTracePrinter'

Finally, to render error information in the error GSP, an HTML-generating printer implementation is needed. The default implementation is org.codehaus.groovy.grails.web.errors.ErrorsViewStackTracePrinter and it's registered as a Spring bean. To use your own implementation, either implement the org.codehaus.groovy.grails.exceptions.StackTraceFilterer directly or subclass ErrorsViewStackTracePrinter and register it in grails-app/conf/spring/resources.groovy as:

Por último, para procesar información de error en error del SGP, es necesaria una implementación de impresora generadora de HTML. La implementación predeterminada es org.codehaus.groovy.grails.web.errors.ErrorsViewStackTracePrinter y está registrada como un bean de Spring. Para utilizar su propia implementación, puede implementar org.codehaus.groovy.grails.exceptions.StackTraceFilterer directamente o hacer una subclase de ErrorsViewStackTracePrinter y regístrarla en grails-app/conf/spring/resources.groovy así:

import com.yourcompany.yourapp.MyErrorsViewStackTracePrinter

beans = {

errorsViewStackTracePrinter(MyErrorsViewStackTracePrinter, ref('grailsResourceLocator')) }