[ 
https://issues.apache.org/jira/browse/LOG4J2-1883?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16055753#comment-16055753
 ] 

Anthony Maire commented on LOG4J2-1883:
---------------------------------------

I made a first draft here : 
https://github.com/m-anthony/logging-log4j2/commit/61c3486aecded6931fe84f19b3cac9daa3d5d0e5
It allows to capture a precise timestamp in LogEvent instance, but displaying 
it is not handled yet

However I am not satisfied at all with this draft for several reasons :
- Using the new Clock API is pretty hard, since getting a timestamp needs 
several method calls. Moreover converting the "nanoseconds from a given 
reference" to seconds + nano since epoch is tricky since we need to handle 
negative value and we don't have access to Math.floorDiv / Math.floorMod 
methods. This leads to a copy/pasting of that query + conversion code for each 
LogEvent implementation, and some ugly hacks for initializing the final fields 
of Log4jLogEvent using the default constructor. The initial motivation was to 
avoid object allocation, but having such a painful API only for performance 
reason is not a good idea at all.
- getTimeMillis() is no longer backed by a field, and it causes some problems 
for serialization. To keep  the tests valid, I had to change the output of the 
serialized events in XML/JSON/JDBC. So there will be some backward 
compatibility issues for users
- Most date formatter are handled through FastDateFormat from Apache Commons 
Lang that does not know how to format timestamp with sub-millisecond 
resolution. We have the same issue with JDK classes : you need JDK8 to have 
sub-millisecond parsing/formatting. So even if we had the precise timestamp, we 
won't be able to integrate it in the standard "\%d" pattern

Basically, to have a clean handling of this feature, Java8 will help a lot, but 
unfortunately we are not using it yet.
Meanwhile, I think we should do only minimal code changes and the best idea 
could be to reuse the nanoTime field that was added for LOG4J2-1076, and use a 
specific pattern converter to format it as the sub-millisecond part of the 
timestamp.
This will limit the impacting change to that niche feature instead of causing 
lots of backward compatibility issues, and wait until log4J migrating to Java 8 
to have a implement a clean integration with the \%d pattern converter

We can create a new pattern converter (or maybe change the meaning of the 
current \%N pattern ?), let's call it \%sm or \%subMillis (Sorry, I cannot find 
a good name ...), it will extract logEvent.nanoTime modulo 1 million (i.e the 
subMilli part of the timestamp) and format it
This pattern can have a parameter which will be the number of digits to 
display. For instance you can use \%d\{ISO8601\}\%sm\{3\} to have a ISO8601 
timestamp with micro-second resolution
The only thing that is missing is a way to inject a precise time source, and 
call it only when needed (since a custom JNR call can be 5 times more costly 
than System.nanoTime if running on Java 9 is not an option).
I think that the simplest thing is :
- Having Clock extends the NanoClock interface, most implementations will 
return 0 here, and SystemClock() will return System.nanoTime() (for now, in 
Java 9 it should be based on java.time.Clock$SystemClock.instant())
- replace in PatternParser.parse() config.setNanoClock(new SystemNanoClock()) 
by config.setNanoClock(ClockFactory.getClock()) when such a patternCOnverter is 
detected

Any further input on this ? 


> Timestamp does not seem to support microseconds level
> -----------------------------------------------------
>
>                 Key: LOG4J2-1883
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-1883
>             Project: Log4j 2
>          Issue Type: Bug
>          Components: Configurators
>         Environment: Linux with any JDK including JDK1.8
>            Reporter: Madhava Dass
>            Priority: Critical
>
> Used log4j and 'log4j2.xml' to configure timestamp format as:
> {code}
> <?xml version="1.0" encoding="UTF-8"?>
> <Configuration status="WARN">
>     <Appenders>
>         <Console name="Console" target="SYSTEM_OUT">
>             <PatternLayout 
> pattern="[%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}{UTC}][%level][%logger{36}]:%msg%n"/>
>         </Console>
>     </Appenders>
>     <Loggers>
>         <Root level="DEBUG">
>             <AppenderRef ref="Console"/>
>         </Root>
>     </Loggers>
> </Configuration>
> {code}
> This pattern produces the time stamp as:
> {code}
> [2017-03-29T13:55:28.363000][null]:[Thread-1]: - <message>
> {code}
> The desired output is:
> {code}
> [2017-03-29T13:55:28.363701-07:00][null]:[Thread-1]: - <message>
> {code}
> Different versions of JDKs were tried including JDK 1.8. It does not seem to 
> make any difference in the outcome.
> Is there a way to get the desired time stamp through pattern matching 
> configuration in the '*.xml' file?



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to