Browse Source

Logger work.

The main change is the new BigProjectLogger that makes reading the results of very big chained/nested projects  manageable. 

Some pulling up of helper methods into DefaultLogger, and a bit of cleanup there; plus the appopriate documentation changes

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@539477 13f79535-47bb-0310-9956-ffa450edef68
master
Steve Loughran 18 years ago
parent
commit
b5e606fe0e
7 changed files with 313 additions and 23 deletions
  1. +2
    -0
      WHATSNEW
  2. +91
    -6
      docs/manual/listeners.html
  3. +34
    -2
      src/main/org/apache/tools/ant/DefaultLogger.java
  4. +11
    -1
      src/main/org/apache/tools/ant/NoBannerLogger.java
  5. +1
    -1
      src/main/org/apache/tools/ant/listener/AnsiColorLogger.java
  6. +171
    -0
      src/main/org/apache/tools/ant/listener/BigProjectLogger.java
  7. +3
    -13
      src/main/org/apache/tools/ant/listener/TimestampedLogger.java

+ 2
- 0
WHATSNEW View File

@@ -148,6 +148,8 @@ Other changes:
<comment> nested element as nested text instead of using the 'value'
attribute.

* A new logger, BigProjectLogger, lists the project name with every target


Changes from Ant 1.6.5 to Ant 1.7.0
===================================


+ 91
- 6
docs/manual/listeners.html View File

@@ -44,13 +44,19 @@ listeners and loggers.</p>
<li>message logged</li>
</ul>

<p>
These are used internally for various recording and housekeeping operations,
however new listeners may registered on the command line through the <code>-listener</code>
argument.
</p>

<h3><a name="Loggers">Loggers</a></h3>

<p>Loggers extend the capabilities of listeners and add the following features:</p>

<ul>
<li>Receives a handle to the standard output and error print streams and
therefore can log information to the console or the -logfile specified file.</li>
therefore can log information to the console or the <code>-logfile</code> specified file.</li>
<li>Logging level (-quiet, -verbose, -debug) aware</li>
<li>Emacs-mode aware</li>
</ul>
@@ -104,7 +110,11 @@ listeners and loggers.</p>
<td width="33%">Prints the time that a build finished</td>
<td width="34%">BuildLogger</td>
</tr>

<tr>
<td width="33%"><code><a href="#BigProjectLogger">org.apache.tools.ant.BigProjectLogger</a></code></td>
<td width="33%">Prints the project name every target</td>
<td width="34%">BuildLogger</td>
</tr>
</table>
<h3><a name="DefaultLogger">DefaultLogger</a></h3>

@@ -235,7 +245,7 @@ in the console using applications like cat, more, etc.</p>
color codes. It works on XTerm, ETerm, Win9x Console
(with ANSI.SYS loaded.), etc.</p>
<p><Strong>NOTE:</Strong>
It doesn't work on WinNT even when a COMMAND.COM console loaded with
It doesn't work on WinNT and successors, even when a COMMAND.COM console loaded with
ANSI.SYS is used.</p>
<p>If the user wishes to override the default colors
with custom ones, a file containing zero or more of the
@@ -318,7 +328,7 @@ corresponding Log4j level.</p>

</blockquote>

<p>To use Log4j you will need the Log4j jar file and a 'log4j.properties'
<p>To use Log4j you will need the Log4j JAR file and a 'log4j.properties'
configuration file. Both should be placed somewhere in your Ant
classpath. If the log4j.properties is in your project root folder you can
add this with <i>-lib</i> option:</p>
@@ -386,6 +396,7 @@ is declared at all.
<pre>
BUILD SUCCESSFUL - at 16/08/05 16:24
</pre>
<p>To use this listener, use the command:</p>

<blockquote>

@@ -393,6 +404,63 @@ is declared at all.

</blockquote>

<h3><a name="BigProjectLogger">BigProjectLogger</a></h3>

<p>
This logger is designed to make examining the logs of a big build easier,
especially those run under continuous integration tools. It
</p>
<ol>
<li>When entering a child project, prints its name and directory</li>
<li>When exiting a child project, prints its name</li>
<li>Includes the name of the project when printing a target</li>
<li>Omits logging the names of all targets that have no direct task output</li>
<li>Includes the build finished timestamp of the TimeStamp logger</li>
</ol>
<p>
This is useful when using &lt;subant&gt; to build a large project
from many smaller projects -the output shows which particular
project is building. Here is an example in which "clean" is being called
on all a number of child projects, only some of which perform work:
</p>
<pre>

======================================================================
Entering project "xunit"
In /home/ant/components/xunit
======================================================================

xunit.clean:
[delete] Deleting directory /home/ant/components/xunit/build
[delete] Deleting directory /home/ant/components/xunit/dist

======================================================================
Exiting project "xunit"
======================================================================

======================================================================
Entering project "junit"
In /home/ant/components/junit
======================================================================

======================================================================
Exiting project "junit"
======================================================================
</pre>

<p>
The entry and exit messages are very verbose in this example, but in
a big project compiling or testing many child components, the messages
are reduced to becoming clear delimiters of where different projects
are in charge -or more importantly, which project is failing.
</p>

<p>To use this listener, use the command:</p>
<blockquote>

<code>ant -logger org.apache.tools.ant.listener.BigProjectLogger</code>

</blockquote>

<h2><a name="dev">Writing your own</a></h2>

@@ -402,8 +470,25 @@ developers.</p>
<p>Notes:</p>

<ul>
<li>A listener or logger should not write to standard output or error; Ant
captures these internally and may cause an infinite loop.</li>
<li>
A listener or logger should not write to standard output or error in the <code>messageLogged() method</code>;
Ant captures these internally and it will trigger an infinite loop.
</li>
<li>
Logging is synchronous; all listeners and loggers are called one after the other, with the build blocking until
the output is processed. Slow logging means a slow build.
</li>
<li>When a build is started, and <code>BuildListener.buildStarted(BuildEvent event)</code> is called,
the project is not fully functional. The build has started, yes, and the event.getProject() method call
returns the Project instance, but that project is initialized with JVM and ant properties, nor has it
parsed the build file yet. You cannot call <code>Project.getProperty()</code> for property lookup, or
<code>Project.getName()</code> to get the project name (it will return null).
</li>
<li>
Classes that implement <code>org.apache.tools.ant.SubBuildListener</code> receive notifications when child projects
start and stop.
</li>

</ul>




+ 34
- 2
src/main/org/apache/tools/ant/DefaultLogger.java View File

@@ -22,9 +22,12 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StringReader;
import java.util.Date;
import java.text.DateFormat;

import org.apache.tools.ant.util.DateUtils;
import org.apache.tools.ant.util.StringUtils;
import org.apache.tools.ant.util.FileUtils;

/**
* Writes build events to a PrintStream. Currently, it
@@ -251,9 +254,9 @@ public class DefaultLogger implements BuildLogger {
tmp.append(label);
label = tmp.toString();

BufferedReader r = null;
try {
BufferedReader r =
new BufferedReader(
r = new BufferedReader(
new StringReader(event.getMessage()));
String line = r.readLine();
boolean first = true;
@@ -273,8 +276,14 @@ public class DefaultLogger implements BuildLogger {
} catch (IOException e) {
// shouldn't be possible
message.append(label).append(event.getMessage());
} finally {
if (r != null) {
FileUtils.close(r);
}
}

} else {
//emacs mode or there is no task
message.append(event.getMessage());
}
Throwable ex = event.getException();
@@ -329,4 +338,27 @@ public class DefaultLogger implements BuildLogger {
*/
protected void log(String message) {
}

/**
* Get the current time.
* @return the current time as a formatted string.
* @since Ant1.7.1
*/
protected String getTimestamp() {
Date date = new Date(System.currentTimeMillis());
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
String finishTime = formatter.format(date);
return finishTime;
}

/**
* Get the project name or null
* @param event the event
* @return the project that raised this event
* @since Ant1.7.1
*/
protected String extractProjectName(BuildEvent event) {
Project project = event.getProject();
return project!=null?project.getName():null;
}
}

+ 11
- 1
src/main/org/apache/tools/ant/NoBannerLogger.java View File

@@ -49,7 +49,17 @@ public class NoBannerLogger extends DefaultLogger {
* Must not be <code>null</code>.
*/
public void targetStarted(BuildEvent event) {
targetName = event.getTarget().getName();
targetName = extractTargetName(event);
}

/**
* Override point, extract the target name
* @param event the event to work on
* @return the target name to print
* @since Ant1.7.1
*/
protected String extractTargetName(BuildEvent event) {
return event.getTarget().getName();
}

/**


+ 1
- 1
src/main/org/apache/tools/ant/listener/AnsiColorLogger.java View File

@@ -96,7 +96,7 @@ import org.apache.tools.ant.Project;
* 47 -> White
*
*/
public final class AnsiColorLogger extends DefaultLogger {
public class AnsiColorLogger extends DefaultLogger {
// private static final int ATTR_NORMAL = 0;
// private static final int ATTR_BRIGHT = 1;
private static final int ATTR_DIM = 2;


+ 171
- 0
src/main/org/apache/tools/ant/listener/BigProjectLogger.java View File

@@ -0,0 +1,171 @@
/*
* Copyright 2007 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.listener;

import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.NoBannerLogger;
import org.apache.tools.ant.SubBuildListener;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.util.StringUtils;

import java.io.File;

/**
* This is a special logger that is designed to make it easier to work with big projects, those that use imports and
* subant to build complex systems.
*
* @since Ant1.7.1
*/

public class BigProjectLogger extends NoBannerLogger implements SubBuildListener {

/**
* Header string for the log.
* {@value}
*/
public static final String HEADER="======================================================================";
/**
* Footer string for the log.
* {@value}
*/
public static final String FOOTER=HEADER;

/**
* This is an override point: the message that indicates whether a build failed. Subclasses can change/enhance the
* message.
*
* @return The classic "BUILD FAILED" plus a timestamp
*/
protected String getBuildFailedMessage() {
return super.getBuildFailedMessage() + TimestampedLogger.SPACER + getTimestamp();
}

/**
* This is an override point: the message that indicates that a build succeeded. Subclasses can change/enhance the
* message.
*
* @return The classic "BUILD SUCCESSFUL" plus a timestamp
*/
protected String getBuildSuccessfulMessage() {
return super.getBuildSuccessfulMessage() + TimestampedLogger.SPACER + getTimestamp();
}


/**
* {@inheritDoc}
*
* @param event
*/
public void buildStarted(BuildEvent event) {
super.buildStarted(event);
subBuildStarted(event);
}

/**
* {@inheritDoc}
*
* @param event
*/
public void buildFinished(BuildEvent event) {
subBuildFinished(event);
super.buildFinished(event);
}

/**
* Override point, extract the target name
*
* @param event the event to work on
* @return the target name -including the owning project name (if non-null)
*/
protected String extractTargetName(BuildEvent event) {
String targetName = event.getTarget().getName();
String projectName = extractProjectName(event);
if (projectName != null && targetName != null) {
return projectName + '.' + targetName;
} else {
return targetName;
}
}


/**
* {@inheritDoc}
*
* @param event An event with any relevant extra information. Must not be <code>null</code>.
*/
public void subBuildStarted(BuildEvent event) {
String name = extractNameOrDefault(event);
Project project = event.getProject();

File base = project == null ? null : project.getBaseDir();
String path = base == null ?
"With no base directory"
: "In " + base.getAbsolutePath();
printMessage(StringUtils.LINE_SEP + getHeader()
+ StringUtils.LINE_SEP +"Entering project " + name
+ StringUtils.LINE_SEP + path
+StringUtils.LINE_SEP + getFooter(),
out,
event.getPriority());
}

/**
* Get the name of an event
*
* @param event the event name
* @return the name or a default string
*/
protected String extractNameOrDefault(BuildEvent event) {
String name = extractProjectName(event);
if (name == null) {
name = "";
} else {
name = '"'+name+'"';
}
return name;
}

/** {@inheritDoc} */
public void subBuildFinished(BuildEvent event) {
String name = extractNameOrDefault(event);
String failed = event.getException() != null ? "failing " : "";
printMessage(StringUtils.LINE_SEP + getHeader()
+ StringUtils.LINE_SEP + "Exiting " + failed + "project "
+ name
+ StringUtils.LINE_SEP + getFooter(),
out,
event.getPriority());
}

/**
* Override point: return the header string for the entry/exit message
* @return the header string
*/
protected String getHeader() {
return HEADER;
}

/**
* Override point: return the footer string for the entry/exit message
* @return the footer string
*/
protected String getFooter() {
return FOOTER;
}

}

+ 3
- 13
src/main/org/apache/tools/ant/listener/TimestampedLogger.java View File

@@ -31,14 +31,14 @@ public class TimestampedLogger extends DefaultLogger {
/**
* what appears between the old message and the new
*/
private static final String SPACER = " - at ";
public static final String SPACER = " - at ";


/**
* This is an override point: the message that indicates whether a build failed.
* Subclasses can change/enhance the message.
*
* @return The classic "BUILD FAILED"
* @return The classic "BUILD FAILED" plus a timestamp
*/
protected String getBuildFailedMessage() {
return super.getBuildFailedMessage() + SPACER + getTimestamp();
@@ -48,20 +48,10 @@ public class TimestampedLogger extends DefaultLogger {
* This is an override point: the message that indicates that a build succeeded.
* Subclasses can change/enhance the message.
*
* @return The classic "BUILD SUCCESSFUL"
* @return The classic "BUILD SUCCESSFUL" plus a timestamp
*/
protected String getBuildSuccessfulMessage() {
return super.getBuildSuccessfulMessage() + SPACER + getTimestamp();
}

/**
* Get the current time.
* @return the current time as a formatted string.
*/
protected String getTimestamp() {
Date date = new Date(System.currentTimeMillis());
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
String finishTime = formatter.format(date);
return finishTime;
}
}

Loading…
Cancel
Save