Console output capture

The gradle-jdocbook plugin tries to capture console output and redirect to an output file for the duration of calling one of its delegates (it does xslt processing and the output can be very verbose and you’d really want to see it segmented per-format anyway…). This stopped working during my upgrade from m3 to m8. The output file is created, but no output gets written there. Also, nothing gets output to the console.

The code that tries to do this is in: https://github.com/pressgang/jdocbook-core/blob/master/src/main/java/org/jboss/jdocbook/util/ConsoleRedirectionHandler.java

Any ideas how to get this working again?

Have you tried ‘task.logging.addStandardOutputListener()’ or ‘project.logging.addStandardOutputListener()’?

Peter, nope I have not. Part of the problem is that this is in code that is shared between the Gradle and Maven plugins.

And its not just “listening” that I want to do. These are docbook xsl, which can get VERY chatty (especially the pdf one). I’d really rather just send everything sent to the console during this process to file. Unless I misunderstand, I am thinking a “listener” does not give me that option.

You can configure a task like so:

logging.addStandardOutputListener(myListener)
logging.captureStandardOutput(null) // don't show std out

The low-level way also works fine for me:

task first << {
    def old = System.out
    def stream = new ByteArrayOutputStream()
    System.out = new PrintStream(stream)
    try {
      println "printing to std out..."
      def captured = new String(stream.toByteArray())
      logger.lifecycle("captured: $captured")
    } finally {
      System.out = old
    }
}

Would doing what you call the “low-level way” from a plugin make any difference? All I know is that this is not working in my case…

  redirecting console output to file [/home/steve/projects/pressgang/docbook5-poc/build/docbook/work/log/console-en-US-pdf.log]  Defined font directory /home/steve/projects/pressgang/docbook5-poc/build/docbook/stage/fonts is not exist or is not a directory  Font "Symbol,normal,700" not found. Substituting with "Symbol,normal,400".  Font "ZapfDingbats,normal,700" not found. Substituting with "ZapfDingbats,normal,400".  Couldn't find hyphenation pattern en  Content overflows the viewport of the fo:region-body on page 2 in block-progression direction by 278900 millipoints. (See position -1:-1)  span="inherit" on fo:block, but no explicit value found on the parent FO.  Resetting console output  

In between the first and last line is where “console redirection” is supposed to be in play, but obviously some stuff is not captured.

Depends on what you mean by “from a plugin”. The plugin itself runs in the configuration phase. That’s probably not when you want redirection to happen. The right thing to do is to make redirection happen for (the execution phase of) the plugin’s tasks, independently. If you own the source code of the task implementations, that should work just like I’ve done it in the build script.

That’s all FOP (PDF generator) logging. I wonder if maybe FOP caches System.out reference or something like that…

Seems like it’s not a Gradle-related problem then. I’m resolving this topic for now.

Well I am certainly not able to capture output going to console. I just have no idea why. It is quite likely not Gradle problem as you say…

I’m facing a similar issue with liquibase which definately DOES cache a reference to standard out (grrrr), and I thought I’d come up with a neat workaround, but I’m stumped… In the class I create below I’ve tried a variety of forms including more groovyesqe notation, so please ignore that. What is stumping me is the fact the output of the 3 println statements

[08:08:01][Step 1/1] org.gradle.util.LinePerThreadBufferingOutputStream@539b5b78
[08:08:01][Step 1/1] OutDelegate@1592bfeb

Then later…

[08:08:05][Step 1/1] :updateSQL
[08:08:05][:updateSQL] org.gradle.util.LinePerThreadBufferingOutputStream@539b5b78
public class OutDelegate extends PrintStream {
    public OutDelegate(OutputStream s) { super(s) }
    @Delegate public PrintStream delegate = System.out;
      public PrintStream getDelegate() {
        return delegate;
    }
      public void setDelegate(PrintStream s) {
        delegate = s;
    }
}
  println System.out
System.out = new OutDelegate(System.out)
println System.out
  updateSQL.doFirst {
    println System.out
    if (project.hasProperty('teamcity')) {
        project.ext.outTmp = System.out.getDelegate()
        System.out.setDelegate(new PrintStream(new FileOutputStream("build/dbFull.sql")));
        liquibase.databases.defaultDatabase = liquibase.databases.emptyDB
    }
}
updateSQL.doLast {
    if (project.hasProperty('teamcity')) {
        System.out.getDelegate.close()
        System.out.setDelegate( project.ext.outTmp )
        liquibase.databases.defaultDatabase = liquibase.databases.myDB
    }
}