Source Code for Apache Log4j Core Implementation

Apache Log4j Core Implementation provides the functional components of the logging system. Users are free to create their own plugins and include them in the logging configuration. Apache Log4j Core is a required module to use Apache Log4j.

Bytecode (Java 8) for Apache Log4j Core Implementation is provided in a separate JAR file like log4j-core-2.14.1.jar.

Source Code files for Apache Log4j API are provided in both binary packge like apache-log4j-2.14.1-bin.zip and source package like apache-log4j-2.14.1-src.zip. You can download them at Apache Log4j Website.

You can also browse Source Code files for Apache Log4j Core Implementation 2.14.1 below.

✍: FYIcenter.com

org/apache/logging/log4j/core/pattern/DatePatternConverter.java

/*
 * 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.
 */
package org.apache.logging.log4j.core.pattern;

import java.util.Arrays;
import java.util.Date;
import java.util.Objects;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.util.Constants;
import org.apache.logging.log4j.core.time.Instant;
import org.apache.logging.log4j.core.time.MutableInstant;
import org.apache.logging.log4j.core.util.datetime.FastDateFormat;
import org.apache.logging.log4j.core.util.datetime.FixedDateFormat;
import org.apache.logging.log4j.core.util.datetime.FixedDateFormat.FixedFormat;
import org.apache.logging.log4j.util.PerformanceSensitive;

/**
 * Converts and formats the event's date in a StringBuilder.
 */
@Plugin(name = "DatePatternConverter", category = PatternConverter.CATEGORY)
@ConverterKeys({"d", "date"})
@PerformanceSensitive("allocation")
public final class DatePatternConverter extends LogEventPatternConverter implements ArrayPatternConverter {

    private abstract static class Formatter {
        long previousTime; // for ThreadLocal caching mode
        int nanos;

        abstract String format(final Instant instant);

        abstract void formatToBuffer(final Instant instant, StringBuilder destination);

        public String toPattern() {
            return null;
        }
    }

    private static final class PatternFormatter extends Formatter {
        private final FastDateFormat fastDateFormat;

        // this field is only used in ThreadLocal caching mode
        private final StringBuilder cachedBuffer = new StringBuilder(64);

        PatternFormatter(final FastDateFormat fastDateFormat) {
            this.fastDateFormat = fastDateFormat;
        }

        @Override
        String format(final Instant instant) {
            return fastDateFormat.format(instant.getEpochMillisecond());
        }

        @Override
        void formatToBuffer(final Instant instant, final StringBuilder destination) {
            final long timeMillis = instant.getEpochMillisecond();
            if (previousTime != timeMillis) {
                cachedBuffer.setLength(0);
                fastDateFormat.format(timeMillis, cachedBuffer);
            }
            destination.append(cachedBuffer);
        }

        @Override
        public String toPattern() {
            return fastDateFormat.getPattern();
        }
    }

    private static final class FixedFormatter extends Formatter {
        private final FixedDateFormat fixedDateFormat;

        // below fields are only used in ThreadLocal caching mode
        private final char[] cachedBuffer = new char[70]; // max length of formatted date-time in any format < 70
        private int length = 0;

        FixedFormatter(final FixedDateFormat fixedDateFormat) {
            this.fixedDateFormat = fixedDateFormat;
        }

        @Override
        String format(final Instant instant) {
            return fixedDateFormat.formatInstant(instant);
        }

        @Override
        void formatToBuffer(final Instant instant, final StringBuilder destination) {
            final long epochSecond = instant.getEpochSecond();
            final int nanoOfSecond = instant.getNanoOfSecond();
            if (previousTime != epochSecond || nanos != nanoOfSecond) {
                length = fixedDateFormat.formatInstant(instant, cachedBuffer, 0);
                previousTime = epochSecond;
                nanos = nanoOfSecond;
            }
            destination.append(cachedBuffer, 0, length);
        }

        @Override
        public String toPattern() {
            return fixedDateFormat.getFormat();
        }
    }

    private static final class UnixFormatter extends Formatter {

        @Override
        String format(final Instant instant) {
            return Long.toString(instant.getEpochSecond());
        }

        @Override
        void formatToBuffer(final Instant instant, final StringBuilder destination) {
            destination.append(instant.getEpochSecond()); // no need for caching
        }
    }

    private static final class UnixMillisFormatter extends Formatter {

        @Override
        String format(final Instant instant) {
            return Long.toString(instant.getEpochMillisecond());
        }

        @Override
        void formatToBuffer(final Instant instant, final StringBuilder destination) {
            destination.append(instant.getEpochMillisecond()); // no need for caching
        }
    }

    private final class CachedTime {
        public long epochSecond;
        public int nanoOfSecond;
        public String formatted;

        public CachedTime(final Instant instant) {
            this.epochSecond = instant.getEpochSecond();
            this.nanoOfSecond = instant.getNanoOfSecond();
            this.formatted = formatter.format(instant);
        }
    }

    /**
     * UNIX formatter in seconds (standard).
     */
    private static final String UNIX_FORMAT = "UNIX";

    /**
     * UNIX formatter in milliseconds
     */
    private static final String UNIX_MILLIS_FORMAT = "UNIX_MILLIS";

    private final String[] options;
    private final ThreadLocal<MutableInstant> threadLocalMutableInstant = new ThreadLocal<>();
    private final ThreadLocal<Formatter> threadLocalFormatter = new ThreadLocal<>();
    private final AtomicReference<CachedTime> cachedTime;
    private final Formatter formatter;

    /**
     * Private constructor.
     *
     * @param options options, may be null.
     */
    private DatePatternConverter(final String[] options) {
        super("Date", "date");
        this.options = options == null ? null : Arrays.copyOf(options, options.length);
        this.formatter = createFormatter(options);
        cachedTime = new AtomicReference<>(fromEpochMillis(System.currentTimeMillis()));
    }

    private CachedTime fromEpochMillis(final long epochMillis) {
        final MutableInstant temp = new MutableInstant();
        temp.initFromEpochMilli(epochMillis, 0);
        return new CachedTime(temp);
    }

    private Formatter createFormatter(final String[] options) {
        final FixedDateFormat fixedDateFormat = FixedDateFormat.createIfSupported(options);
        if (fixedDateFormat != null) {
            return createFixedFormatter(fixedDateFormat);
        }
        return createNonFixedFormatter(options);
    }

    /**
     * Obtains an instance of pattern converter.
     *
     * @param options options, may be null.
     * @return instance of pattern converter.
     */
    public static DatePatternConverter newInstance(final String[] options) {
        return new DatePatternConverter(options);
    }

    private static Formatter createFixedFormatter(final FixedDateFormat fixedDateFormat) {
        return new FixedFormatter(fixedDateFormat);
    }

    private static Formatter createNonFixedFormatter(final String[] options) {
        // if we get here, options is a non-null array with at least one element (first of which non-null)
        Objects.requireNonNull(options);
        if (options.length == 0) {
            throw new IllegalArgumentException("Options array must have at least one element");
        }
        Objects.requireNonNull(options[0]);
        final String patternOption = options[0];
        if (UNIX_FORMAT.equals(patternOption)) {
            return new UnixFormatter();
        }
        if (UNIX_MILLIS_FORMAT.equals(patternOption)) {
            return new UnixMillisFormatter();
        }
        // LOG4J2-1149: patternOption may be a name (if a time zone was specified)
        final FixedDateFormat.FixedFormat fixedFormat = FixedDateFormat.FixedFormat.lookup(patternOption);
        final String pattern = fixedFormat == null ? patternOption : fixedFormat.getPattern();

        // if the option list contains a TZ option, then set it.
        TimeZone tz = null;
        if (options.length > 1 && options[1] != null) {
            tz = TimeZone.getTimeZone(options[1]);
        }

        try {
            final FastDateFormat tempFormat = FastDateFormat.getInstance(pattern, tz);
            return new PatternFormatter(tempFormat);
        } catch (final IllegalArgumentException e) {
            LOGGER.warn("Could not instantiate FastDateFormat with pattern " + pattern, e);

            // default to the DEFAULT format
            return createFixedFormatter(FixedDateFormat.create(FixedFormat.DEFAULT, tz));
        }
    }

    /**
     * Appends formatted date to string buffer.
     *
     * @param date date
     * @param toAppendTo buffer to which formatted date is appended.
     */
    public void format(final Date date, final StringBuilder toAppendTo) {
        format(date.getTime(), toAppendTo);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void format(final LogEvent event, final StringBuilder output) {
        format(event.getInstant(), output);
    }

    public void format(final long epochMilli, final StringBuilder output) {
        final MutableInstant instant = getMutableInstant();
        instant.initFromEpochMilli(epochMilli, 0);
        format(instant, output);
    }

    private MutableInstant getMutableInstant() {
        if (Constants.ENABLE_THREADLOCALS) {
            MutableInstant result = threadLocalMutableInstant.get();
            if (result == null) {
                result = new MutableInstant();
                threadLocalMutableInstant.set(result);
            }
            return result;
        }
        return new MutableInstant();
    }

    public void format(final Instant instant, final StringBuilder output) {
        if (Constants.ENABLE_THREADLOCALS) {
            formatWithoutAllocation(instant, output);
        } else {
            formatWithoutThreadLocals(instant, output);
        }
    }

    private void formatWithoutAllocation(final Instant instant, final StringBuilder output) {
        getThreadLocalFormatter().formatToBuffer(instant, output);
    }

    private Formatter getThreadLocalFormatter() {
        Formatter result = threadLocalFormatter.get();
        if (result == null) {
            result = createFormatter(options);
            threadLocalFormatter.set(result);
        }
        return result;
    }

    private void formatWithoutThreadLocals(final Instant instant, final StringBuilder output) {
        CachedTime cached = cachedTime.get();
        if (instant.getEpochSecond() != cached.epochSecond || instant.getNanoOfSecond() != cached.nanoOfSecond) {
            final CachedTime newTime = new CachedTime(instant);
            if (cachedTime.compareAndSet(cached, newTime)) {
                cached = newTime;
            } else {
                cached = cachedTime.get();
            }
        }
        output.append(cached.formatted);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void format(final Object obj, final StringBuilder output) {
        if (obj instanceof Date) {
            format((Date) obj, output);
        }
        super.format(obj, output);
    }

    @Override
    public void format(final StringBuilder toAppendTo, final Object... objects) {
        for (final Object obj : objects) {
            if (obj instanceof Date) {
                format(obj, toAppendTo);
                break;
            }
        }
    }

    /**
     * Gets the pattern string describing this date format.
     *
     * @return the pattern string describing this date format.
     */
    public String getPattern() {
        return formatter.toPattern();
    }

}

org/apache/logging/log4j/core/pattern/DatePatternConverter.java

 

Or download all of them as a single archive file:

File name: log4j-core-2.14.1-sources.jar
File size: 1281358 bytes
Release date: 2021-03-06
Download 

 

Source Code for Apache Log4j JDK Logging Adapter

Source Code for Apache Log4j API

Downloading and Reviewing Apache Log4j Packages

⇑⇑ FAQ for Apache Log4j

2015-11-03, 85435👍, 0💬