Grails Programmer : How to log from a none Grails Artifact

Create a grails app with the rest profile:

$ grails create-app lognongrailsartifact --profile=rest-api

Create a controller grails-app/controllers/lognongrailsartifact/TestController.groovy

package lognongrailsartifact

import static org.springframework.http.HttpStatus.OK

class TestController {

    def index() { 
    	new NonGrailsArtifact().greet()

        render text:"OK", status: OK

    }
}

Create a Groovy Class src/main/groovy/lognongrailsartifact/NonGrailsArtifact.groovy; not a grails artifact.

Note: Grails artefacts get log auto-injected. You will need to inject it manually in this class.

package lognongrailsartifact

import org.apache.commons.logging.LogFactory

class NonGrailsArtifact {
	private static final log = LogFactory.getLog(this)

	void greet() {
		log.info 'Hi'
	}
}

Edit grails-app/conf/logback.groovy

import grails.util.BuildSettings
import grails.util.Environment

// See http://logback.qos.ch/manual/groovy.html for details on configuration
appender('STDOUT', ConsoleAppender) {
    encoder(PatternLayoutEncoder) {
        pattern = "%level %logger - %msg%n"
    }
}

root(ERROR, ['STDOUT'])
logger 'lognongrailsartifact.NonGrailsArtifact', INFO, ['STDOUT']

def targetDir = BuildSettings.TARGET_DIR
if (Environment.isDevelopmentMode() && targetDir) {
    appender("FULL_STACKTRACE", FileAppender) {
        file = "${targetDir}/stacktrace.log"
        append = true
        encoder(PatternLayoutEncoder) {
            pattern = "%level %logger - %msg%n"
        }
    }
    logger("StackTrace", ERROR, ['FULL_STACKTRACE'], false)
}

Run the app

grails> run-app
| Running application...
Grails application running at http://localhost:8080 in environment: development

Invoke the controller

$ curl -X "GET" "http://localhost:8080/test" -H "Accept: application/json"

And you will see the log statement:

grails> INFO lognongrailsartifact.NonGrailsArtifact - Hi

Soeren Glasius pointed me to a more elegant way to it with an AST.

package lognongrailsartifact
 
import groovy.util.logging.Log4j
 
@Log4j
class NonGrailsArtifact {
    void greet() {
        log.info 'Hi'
    }
} 

An even better approach, as pointed by Alvaro Sanchez, will be to do it with @Slf4j.

package lognongrailsartifact

import groovy.util.logging.Slf4j

@Slf4j
class NonGrailsArtifact {
    void greet() {
        log.info 'Hi'
    }
} 

SLF4J vs LOG4J Which one to prefer?. SLF4J is basically an abstraction layer. It is not a logging implementation. It means that if you’re writing a library and you use SLF4J, you can give that library to someone else to use and they can choose which logging implementation to use with SLF4J e.g. log4j or the Java logging API

Do you like to read about Grails / Groovy development? If the answer is yes, subscribe to Groovy Calamari. A weekly curated email newsletter about the Groovy ecosystem. Curated by me 🎉

3 thoughts on “Grails Programmer : How to log from a none Grails Artifact

  1. Alvaro Sanchez-Mariscal

    There’s a much better way: just annotate the non-artifact class with Groovy’s @Slf4j AST transformation.

    Reply
  2. Søren Berg Glasius

    Why not use Groovy’s AST transformation for logging:

    package lognongrailsartifact
    import groovy.transform.Log4j

    import org.apache.commons.logging.LogFactory

    @Log4j
    class NonGrailsArtifact {
    void greet() {
    log.info ‘Hi’
    }
    }

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *