Thursday, September 3, 2009

Improving Ant output

Ant is a very popular build tool in Java environments. Numerous tasks have been developed for it that allow integration with various services and products quite easy.

One area Ant could improve in is output. Running a typical build file produces a lot of output that is not really relevant to the user. Also, when an error occurs, it would be nice to have a stack trace giving more information, but then you need to rerun Ant with the -verbose option, which enables verbose output for all tasks, not just the failing one.

And note that there may be situations in which rerunning the task is suboptimal:
  • the error does not occur again (but it may come back to hunt you later on)
  • executing the build takes a lot of time
Here are some guidelines I propose for improving Ant output:
  1. keep output to stdout very limited;
  2. after completion of the build run, provide access to more output, including the stacktrace, without rerunning the task
Here's an example of some Ant output:
-init-properties:

-init-site-properties:

check-questions:

transform-questions-xml:
[xmlvalidate2] 10 file(s) have been successfully validated.
[xslt] Transforming into /Users/ernst/albizia/build/contentdbsrc/xsite/content
[xslt] Processing /Users/ernst/albizia/build/contentdbsrc/xsite/content/AOW.QuestionsCategory.xml to /Users/ernst/albizia/build/contentdbsrc/xsite/content/Vragen_AOW.SourcePage.xml
[xslt] Loading stylesheet /Users/ernst/albizia/src/build-xslt/PreprocessQuestions.xslt
[xslt] Processing /Users/ernst/albizia/build/contentdbsrc/xsite/content/Berekenen.QuestionsCategory.xml to /Users/ernst/albizia/build/contentdbsrc/xsite/content/Vragen_Berekenen.SourcePage.xml
The output from the xmlvalidate2 task is very brief. That's nice. In fact the question is whether the output should be shown at all. The output from the xslt task, however, is quite verbose. Instead of listing all files being processed, it could just give a summary of what it did. When -verbose is passed, it could output what is currently output.

Here are some possible options for achieving the goals I stated above:
  1. When a certain Ant option is enabled (which could at some point be enabled by default), send all verbose output to a file on the file system, for example build.log or .build.log. This file can be examined by the user after the build is finished (or cancelled).
  2. When using the default output mode for stdout, do not output the names of tasks that are not actually run (depending on the if and unless attributes).
  3. By default make all tasks just output a single line with a summary of what it did.
  4. Do not put an empty line between each executed task.
  5. When using this mode, use fixed-width output for the target names, and put the task output behind that. Target and task names may have to be cropped for that. For example:
    -init-prope.:
    -init-site-.:
    check-quest.:
    transform-q.:xmlvali.: 10 file(s) validated.
       xslt: 15 file(s) processed, 0 unmodified file(s) skipped.
Note that the output Ant 1.7.1 currently produces when running Ant with the -verbose option is always available after the build run, so the reduction of initial output is not limiting the investigation options for the user, but is in fact extending those.

What do you think of this? Do you consider the current Ant output too verbose or just fine? Have you every had issues examining why an Ant build failed and you wish you would have passed -verbose in the first place? And what do you think of the suggested changes?

5 comments:

  1. One big area that is flawed is unit testing with JUnit. When a problem occurs you get a stack trace from Ant through JUnit invocation, but no stack trace from within the unit test where the actual failure occurs. This is pretty useless.

    Regarding log-spew, we use Ant with CruiseControl and Ant output is the primary cause of huge useless logs. Often the logs do not have any useful information indicating the reason for failure.

    ReplyDelete
  2. One thing that should have been an out of the box feature is to output a file called build.log by default. All build output goes there and only a blow by blow of what module is being constructed should be displayed. We wrote a bunch of infrastructure to accomplish part of this, but the point being, we should not have had to do this. Sigh, I miss the days of using GNU Make!

    ReplyDelete
  3. Robert, indeed the Ant logs in the context of continuous integration runs are one of the sources of my unhappiness (I use Hudson).

    Currently I've got only two options: (1) always produce lots of verbose output, making the build logs extremely hard to wade through or (2) never produce verbose output, requiring me to temporarily enable it once I've got an issue I need to investigate.

    Note that a complete build takes about 11 minutes in my continuous integration environment, so I'd rather not have to rerun that at all.

    If you already developed some code for outputing a build.log file by default, could you make that free and open-source? Perhaps it can be integrated into Ant at some point. And in the mean time, I could use and extend it. May I suggest github? :-)

    ReplyDelete
  4. Sometimes ant output is too verbose as some ant tasks are too talkative IMO, f.e. copy, cvs ..
    Ant core has features to set the loglevel for the whole build but lacks a feature that allows to set the loglevel _inside_ the script for selective tasks only

    But there are solutions, like own loggers or special tasks =
    years ago i read about a setloglevel task on a blog - don't remember where - so the idea for that task is not mine.
    Only had to change the code that has been posted a bit to make it work

    The task is very simple, but very useful, see source =
    http://marc.info/?l=ant-user&m=115504180503962&w=2

    This little task should be part of ant core
    - use it quit often for chatty :-) tasks - but i don't know how to get it into ant core, and finally it's not grown in my brain
    originally ..


    Regards, Gilbert

    ReplyDelete
  5. I wish they would put a verbose attribute support in all tasks by default

    some times some targets are critical, and i would like to have verbose output only in some, but not others

    :)

    ReplyDelete