001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017package org.apache.log4j.pattern;
018
019import org.apache.logging.log4j.core.LogEvent;
020import org.apache.logging.log4j.core.config.plugins.Plugin;
021import org.apache.logging.log4j.core.pattern.ConverterKeys;
022import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
023import org.apache.logging.log4j.core.pattern.PatternConverter;
024import org.apache.logging.log4j.util.TriConsumer;
025
026/**
027 * Able to handle the contents of the LogEvent's MDC and either
028 * output the entire contents of the properties, or to output the value of a specific key
029 * within the property bundle when this pattern converter has the option set.
030 */
031@Plugin(name = "Log4j1MdcPatternConverter", category = PatternConverter.CATEGORY)
032@ConverterKeys({ "properties" })
033public final class Log4j1MdcPatternConverter extends LogEventPatternConverter {
034    /**
035     * Name of property to output.
036     */
037    private final String key;
038
039    /**
040     * Private constructor.
041     *
042     * @param options options, may be null.
043     */
044    private Log4j1MdcPatternConverter(final String[] options) {
045        super(options != null && options.length > 0 ? "Log4j1MDC{" + options[0] + '}' : "Log4j1MDC", "property");
046        if (options != null && options.length > 0) {
047            key = options[0];
048        } else {
049            key = null;
050        }
051    }
052
053    /**
054     * Obtains an instance of PropertiesPatternConverter.
055     *
056     * @param options options, may be null or first element contains name of property to format.
057     * @return instance of PropertiesPatternConverter.
058     */
059    public static Log4j1MdcPatternConverter newInstance(final String[] options) {
060        return new Log4j1MdcPatternConverter(options);
061    }
062
063    /**
064     * {@inheritDoc}
065     */
066    @Override
067    public void format(final LogEvent event, final StringBuilder toAppendTo) {
068        if (key == null) {
069            // if there is no additional options, we output every single Key/Value pair for the MDC
070            toAppendTo.append('{');
071            event.getContextData().forEach(APPEND_EACH, toAppendTo);
072            toAppendTo.append('}');
073        } else {
074            // otherwise they just want a single key output
075            final Object val = event.getContextData().getValue(key);
076            if (val != null) {
077                toAppendTo.append(val);
078            }
079        }
080    }
081
082    private static TriConsumer<String, Object, StringBuilder> APPEND_EACH = (key, value, toAppendTo) -> toAppendTo.append('{').append(key).append(',').append(value).append('}');
083}