Configure Ant logging to show timestamps?

672 views
Skip to first unread message

Eliot Kimber

unread,
Sep 10, 2014, 9:30:58 AM9/10/14
to dita-o...@googlegroups.com
Is it possible (and how would I go about) configuring the ant logging used by the OT to include timestamps with each message, including XSLT-generated messages.

I'm trying to determine the time taken by different parts of my XSLT processes and having time stamps on XSLT messages would be sufficient to my purposes (there's no standard way to get timings of XSLT processing using XSLT-defined facilities).

Thanks,

Eliot

--
Eliot Kimber

que...@gmail.com

unread,
Sep 10, 2014, 11:29:39 AM9/10/14
to dita-o...@googlegroups.com
I can think of several ways. One way to get probably more information than you want, but it includes timestamps for XSLT-generated messages, involves configuring log4j.

1. Get log4j https://logging.apache.org/log4j/1.2/download.html (Instructions would be slightly different if you use 2..x.
2. To make instructions easier, let's put the jar in the dita-ot root directory (log4j-1.2.17.jar or a similarly named jar file would be in the log4j distribution).
2. Create log4j.xml containing:

<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender name="console" class="org.apache.log4j.ConsoleAppender">
    <param name="Target" value="System.out"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d - %m%n"/>
    </layout>
  </appender>
  <root>
    <priority value ="info" />
    <appender-ref ref="console" />
  </root>
 
</log4j:configuration>

3. Add log4j and the directory containing log4.xml to the classpath. To make instructions easier, let's alter startcmd.bat. Before the line that beings with "start", add:

set CLASSPATH=%DITA_DIR%;%CLASSPATH%
set CLASSPATH=%DITA_DIR%\log4j-1.2.17.jar;%CLASSPATH%

4. Configure ant. To make instructions easier, let's use args.input and transtype only:

ant -listener org.apache.tools.ant.listener.Log4jListener -Dargs.input=my.ditamap -Dtranstype=pdf

Like I said this probably logs a lot more information than you want. But, it includes output from xsl:message.

Kendall

que...@gmail.com

unread,
Sep 26, 2014, 5:45:29 PM9/26/14
to dita-o...@googlegroups.com
I thought about this question today for some reason. Since part is about how functions idempotent so you can't use current-dateTime() to get different times, if what you really want is to put timestamps in certain places, you can do that instead of changing logging.

If you can assume that you will be using saxon for your test, and you are willing to assume that the the XSLT statements will be evaluated in order, then you can use java extension functions. I figure that that is a reasonable assumption for one's test code. Not for production code. For example:

<xsl:transform version="2.0"
               xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
               xmlns:f="f"
               exclude-result-prefixes="#all">

  <xsl:output method="text"/>

  <xsl:function name="f:now"
                xmlns:date="java:java.util.Date"
                exclude-result-prefixes="#all">
    <xsl:sequence select="date:new()"/>
  </xsl:function>

  <xsl:function name="f:timestamp"
                xmlns:date="java:java.util.Date"
                xmlns:date-format="java:java.text.SimpleDateFormat"
                exclude-result-prefixes="#all">
    <xsl:param name="fmt"/>
    <xsl:param name="d"/>
    <xsl:value-of select="date-format:format(date-format:new($fmt), $d)"/>
  </xsl:function>

  <xsl:function name="f:timestamp"
                xmlns:date="java:java.util.Date"
                exclude-result-prefixes="#all">
    <xsl:param name="fmt"/>
    <xsl:value-of select="f:timestamp($fmt, date:new())"/>
  </xsl:function>

  <xsl:function name="f:duration"
                xmlns:date="java:java.util.Date"
                xmlns:time="java:java.util.concurrent.TimeUnit"
                exclude-result-prefixes="#all">
    <xsl:param name="s"/>
    <xsl:param name="e"/>
    <xsl:variable name="since" select="date:get-time($e) - date:get-time($s)"/>
    <xsl:sequence select="(time:to-hours(time:MILLISECONDS(), $since),
                          time:to-minutes(time:MILLISECONDS(), $since),
                          time:to-seconds(time:MILLISECONDS(), $since),
                          time:to-millis(time:MILLISECONDS(), $since) mod 1000)"/>
  </xsl:function>

  <xsl:template match="/">
      <xsl:variable name="start-time" select="f:now()"/>
      <xsl:message><xsl:value-of select="concat('Starting at ', f:timestamp('yyyy-MM-dd hh:mm:ss.S', $start-time))"/></xsl:message>
      <xsl:message>Working...</xsl:message>
      <xsl:value-of xmlns:thread="java:java.lang.Thread"
                    select="thread:sleep(5000)"/>
      <xsl:variable name="end-time" select="f:now()"/>
      <xsl:message><xsl:value-of select="concat('Ending at ', f:timestamp('yyyy-MM-dd hh:mm:ss.S', $end-time))"/></xsl:message>
      <xsl:variable name="duration" select="f:duration($start-time, $end-time)"/>
      <xsl:message><xsl:value-of select="concat($duration[1], ' hours&#10;',
                                                $duration[2], ' minutes&#10;',
                                                $duration[3], ' seconds&#10;',
                                                $duration[4], ' milliseconds')"/></xsl:message>
  </xsl:template>
</xsl:transform>

The duration function returns a sequence with hours, minutes, seconds and milliseconds. You pass it a start and end time and the result represents the duration.


Kendall

On Wednesday, September 10, 2014 6:30:58 AM UTC-7, Eliot Kimber wrote:

que...@gmail.com

unread,
Sep 28, 2014, 4:00:08 PM9/28/14
to dita-o...@googlegroups.com
If I am the only one interested in this, sorry for bothering the list. I thought it would be better to rely less on java and more on XPath.

Here time is passed around as a 2 item sequence of a dateTime followed by the number of milliseconds.

It's marshalled/unmarshalled by java-to-timestamp and timestamp-to-java.

The point being that you can use XPath functions like format-dateTime on the first item in the sequence, instead of java functions for formatting. And, you still have milliseconds available, unlike with XPath:


<xsl:transform version="2.0"
               xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"

               xmlns:f="f"
               exclude-result-prefixes="#all">

  <xsl:output method="text"/>

  <xsl:function name="f:now"
                xmlns:date="java:java.util.Date"
                exclude-result-prefixes="#all">
    <xsl:sequence select="f:java-to-timestamp(date:new())"/>
  </xsl:function>

  <xsl:function name="f:java-to-timestamp"

                xmlns:date-format="java:java.text.SimpleDateFormat"
                exclude-result-prefixes="#all">
    <xsl:param name="now"/>
    <xsl:variable name="date-fmt" select="date-format:new('yyyy-MM-dd')"/>
    <xsl:variable name="date" select="date-format:format($date-fmt, $now)"/>
    <xsl:variable name="time-fmt" select="date-format:new('HH:mm:ss')"/>
    <xsl:variable name="time" select="date-format:format($time-fmt, $now)"/>
    <xsl:variable name="millis-fmt" select="date-format:new('S')"/>
    <xsl:sequence select="xs:dateTime(concat($date, 'T', $time)),
                          date-format:format($millis-fmt, $now)"/>
  </xsl:function>

  <xsl:function name="f:timestamp-to-java"
                xmlns:c="java:java.util.Calendar"
                xmlns:date-format="java:java.text.SimpleDateFormat"
                xmlns:p="java:java.text.ParsePosition">
    <xsl:param name="dt"/>
    <xsl:variable name="fmt">[H0001]/[M01]/[D01] [H01]:[m01]:[s01]</xsl:variable>
    <xsl:variable name="dt-text"
                  select="concat(format-dateTime($dt[1], $fmt),
                                 '.',
                                 $dt[2])"/>
    <xsl:variable name="date-fmt" select="date-format:new('hhhh/MM/dd HH:mm:ss.S')"/>
    <xsl:sequence select="date-format:parse($date-fmt, $dt-text, p:new(0))"/>

  </xsl:function>

  <xsl:function name="f:duration"
                xmlns:date="java:java.util.Date"
                xmlns:c="java:java.util.Calendar"
                xmlns:p="java:java.text.ParsePosition"

                xmlns:time="java:java.util.concurrent.TimeUnit"
                exclude-result-prefixes="#all">
    <xsl:param name="s"/>
    <xsl:param name="e"/>
    <xsl:variable name="ts" select="f:timestamp-to-java($s)"/>
    <xsl:variable name="te" select="f:timestamp-to-java($e)"/>
    <xsl:variable name="since" select="date:get-time($te) - date:get-time($ts)"/>

    <xsl:sequence select="(time:to-hours(time:MILLISECONDS(), $since),
                          time:to-minutes(time:MILLISECONDS(), $since),
                          time:to-seconds(time:MILLISECONDS(), $since),
                          time:to-millis(time:MILLISECONDS(), $since) mod 1000)"/>
  </xsl:function>

  <xsl:template match="/">
    <xsl:variable name="start-time" select="f:now()"/>
    <xsl:variable name="fmt">[h].[m02] [P] on [FNn], [D1o] [MNn]</xsl:variable>


    <xsl:message>
      <xsl:value-of select="concat('Starting at ',
                                   $start-time[2], ' milliseconds after ',
                                   format-dateTime($start-time[1], $fmt))"/>
    </xsl:message>

    <xsl:message>Working...</xsl:message>
    <xsl:value-of xmlns:thread="java:java.lang.Thread"
                  select="thread:sleep(5000)"/>

    <xsl:variable name="end-time" select="f:now()"/>
    <xsl:message>
      <xsl:value-of select="concat('Ending at ',
                                    $end-time[2], ' milliseconds after ',
                                    format-dateTime($end-time[1], $fmt))"/>
    </xsl:message>

    <xsl:variable name="duration" select="f:duration($start-time, $end-time)"/>
    <xsl:message>
      <xsl:value-of select="concat($duration[1], ' hours&#10;',
                                   $duration[2], ' minutes&#10;',
                                   $duration[3], ' seconds&#10;',
                                   $duration[4], ' milli-seconds')"/>

    </xsl:message>
  </xsl:template>

</xsl:transform>


Kendall

Eliot Kimber

unread,
Sep 28, 2014, 6:56:26 PM9/28/14
to dita-o...@googlegroups.com
I think a Java extension is a reasonable way to address this requirement generally, and in the context of the DITA Open Toolkit, where there are already Java Saxon extensions, it is definitely a way to proceed. More generally, I try to avoid Java XSLT extensions because it introduces a hard-to-manage configuration challenge in certain environments.

Cheers,

E.

--
You received this message because you are subscribed to the Google Groups "DITA-OT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dita-ot-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Eliot Kimber
Reply all
Reply to author
Forward
0 new messages