// 
//     Licensed to the Apache Software Foundation (ASF) under one
//     or more contributor license agreements.  See the NOTICE file
//     distributed with this work for additional information
//     regarding copyright ownership.  The ASF licenses this file
//     to you 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.
//

= DevFaqAddTimestampToLogs
:jbake-type: wiki
:jbake-tags: wiki, devfaq, needsreview
:jbake-status: published
:keywords: Apache NetBeans wiki DevFaqAddTimestampToLogs
:description: Apache NetBeans wiki DevFaqAddTimestampToLogs
:toc: left
:toc-title:
:syntax: true

== How Do I Add a Timestamp to the Logs?

This FAQ entry demonstrates how to prepend a timestamp to your log file entries. For example:

[source,java]
----

05:42:51.210 CONFIG [com.emxsys.wmt.core.project.GlobalActionContextProxy]: Creating a proxy ....
05:42:51.295 WARNING [org.openide.filesystems.Ordering]: Not all children in ....
05:42:52.151 INFO [org.netbeans.core.startup.NbEvents]: Turning on modules: ....
----

=== Caveats

The NetBeans Platform includes its own logging mechanism.  If you customize the logging through the use of the _java.util.logging.config.file_ or _java.util.logging.config.class_ property settings, then the native NetBeans logging mechanism is completely disabled, and either the default Java logging or your custom logging class is used instead.

=== Solution

This solution shows how to customize the output from the native NetBeans log formatter (_NbFormatter_) by creating a new custom formatter that by prepends a timestamp to the log messages.  Note, using _NbFormatter_ requires a private package reference to the _org-netbeans-core-startup_ module.  This FAQ will also show how to establish the private package access.

==== Step 1. Establish Project Dependencies

Include the a dependency on *org-netbeans-core-startup* in the project that will implement the custom formatter. In Maven, add following entry to the project POM:

[source,xml]
----

<dependency>
    <!--Private Package References: see maven plugin dependencies ...-->
    <artifactId>org-netbeans-core-startup</artifactId>
    <groupId>org.netbeans.modules</groupId>
    <version>${netbeans.version}</version>
</dependency>

----

==== Step 2. Create the Custom Log Formatter

Here's an example of a custom _Formatter_.  It uses the NetBeans _NbFormatter_ instance to obtain a formatted message from the _LogRecord_.  NbFormatter is a final class that exposes itself via a public static _FORMATTER_ property. This solution simply prepends a timestamp, extracted from the LogRecord, to the formatted log message. 

[source,java]
----

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
import org.netbeans.core.startup.logging.NbFormatter; // Private Package Referenced: See POM notes.

public class LogFormatter extends Formatter {

    @Override
    public String format(LogRecord record) {
        String logMsg = NbFormatter.FORMATTER.format(record);
        StringBuilder sb = new StringBuilder();

        // Prepend a timestamp
        Instant instant = Instant.ofEpochMilli(record.getMillis());
        ZonedDateTime timestamp = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
        sb.append(timestamp.toLocalTime.toString());
        sb.append(' ');
        sb.append(logMsg);
        
        return sb.toString();
    }
}

----

==== Step 3. Override the Default Formatters

In a module _Installer_ class, include the following code block in the restored method to replace the default formatters with the custom formatter:

[source,java]
----

public class Installer extends ModuleInstall {

    @Override
    public void restored() {

        // Override the default formatters with the custom formatter
        LogFormatter formatter = new LogFormatter(); // Custom formatter
        Logger logger = Logger.getLogger ("");       // Root logger
        Handler[] handlers = logger.getHandlers();
        for (Handler handler : handlers) {
            handler.setFormatter(formatter);
        }
    }
} 

----

==== Step 4. Configure Access to Private Package

In the project's POM, edit the *nbm-maven-plugin* configuration to allow  private package access to *org.netbeans.modules:org-netbeans-core-startup* via an *impl* module dependency, for example:

[source,xml]
----

<plugin>
    <artifactId>nbm-maven-plugin</artifactId>
    <groupId>org.codehaus.mojo</groupId>
    <extensions>true</extensions>
    <configuration>
        <moduleDependencies>
            <dependency>
                <!--Private Package Reference-->
                <id>org.netbeans.modules:org-netbeans-core-startup</id>
                <type>impl</type>
            </dependency>
        </moduleDependencies>
    </configuration>
</plugin>

----

=== Final Notes

To leverage the NetBeans logging, you must disable any _java.util.logging.config.file_ or _java.util.logging.config.class_ property settings.  Check your application's .conf file, and, in the application's POM, check the _additionalArguments_ entry.

<hr/>

This example was tested with NetBeans 8.0 and JDK 8.

=== Apache Migration Information

The content in this page was kindly donated by Oracle Corp. to the
Apache Software Foundation.

This page was exported from link:http://wiki.netbeans.org/DevFaqAddTimestampToLogs[http://wiki.netbeans.org/DevFaqAddTimestampToLogs] , 
that was last modified by NetBeans user Bdschubert 
on 2014-06-21T13:31:08Z.


*NOTE:* This document was automatically converted to the AsciiDoc format on 2018-02-07, and needs to be reviewed.
