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.logging.log4j.core;
018
019import java.util.List;
020
021import org.apache.logging.log4j.core.config.Property;
022import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
023import org.apache.logging.log4j.core.impl.ThreadContextDataInjector;
024import org.apache.logging.log4j.util.ReadOnlyStringMap;
025import org.apache.logging.log4j.util.StringMap;
026
027/**
028 * Responsible for initializing the context data of LogEvents. Context data is data that is set by the application to be
029 * included in all subsequent log events.
030 * <p><b>NOTE: It is no longer recommended that custom implementations of this interface be provided as it is
031 * difficult to do. Instead, provide a custom ContextDataProvider.</b></p>
032 * <p>
033 * <p>
034 * The source of the context data is implementation-specific. The default source for context data is the ThreadContext.
035 * </p><p>
036 * In some asynchronous models, work may be delegated to several threads, while conceptually this work shares the same
037 * context. In such models, storing context data in {@code ThreadLocal} variables is not convenient or desirable.
038 * Users can configure the {@code ContextDataInjectorFactory} to provide custom {@code ContextDataInjector} objects,
039 * in order to initialize log events with context data from any arbitrary context.
040 * </p><p>
041 * When providing a custom {@code ContextDataInjector}, be aware that the {@code ContextDataInjectorFactory} may be
042 * invoked multiple times and the various components in Log4j that need access to context data may each have their own
043 * instance of {@code ContextDataInjector}.
044 * This includes the object(s) that populate log events, but also various lookups and filters that look at
045 * context data to determine whether an event should be logged.
046 * </p><p>
047 * Implementors should take particular note of how the different methods in the interface have different thread-safety
048 * guarantees to enable optimal performance.
049 * </p>
050 *
051 * @see StringMap
052 * @see ReadOnlyStringMap
053 * @see ContextDataInjectorFactory
054 * @see org.apache.logging.log4j.ThreadContext
055 * @see ThreadContextDataInjector
056 * @since 2.7
057 */
058public interface ContextDataInjector {
059    /**
060     * Returns a {@code StringMap} object initialized with the specified properties and the appropriate
061     * context data. The returned value may be the specified parameter or a different object.
062     * <p>
063     * This method will be called for each log event to initialize its context data and implementors should take
064     * care to make this method as performant as possible while preserving at least the following thread-safety
065     * guarantee.
066     * </p><p>
067     * Thread-safety note: The returned object can safely be passed off to another thread: future changes in the
068     * underlying context data will not be reflected in the returned object.
069     * </p><p>
070     * Example implementation:
071     * </p>
072     * <pre>
073     * public StringMap injectContextData(List<Property> properties, StringMap reusable) {
074     *     if (properties == null || properties.isEmpty()) {
075     *         // assume context data is stored in a copy-on-write data structure that is safe to pass to another thread
076     *         return (StringMap) rawContextData();
077     *     }
078     *     // first copy configuration properties into the result
079     *     ThreadContextDataInjector.copyProperties(properties, reusable);
080     *
081     *     // then copy context data key-value pairs (may overwrite configuration properties)
082     *     reusable.putAll(rawContextData());
083     *     return reusable;
084     * }
085     * </pre>
086     *
087     * @param properties Properties from the log4j configuration to be added to the resulting ReadOnlyStringMap. May be
088     *          {@code null} or empty
089     * @param reusable a {@code StringMap} instance that may be reused to avoid creating temporary objects
090     * @return a {@code StringMap} instance initialized with the specified properties and the appropriate
091     *          context data. The returned value may be the specified parameter or a different object.
092     * @see ThreadContextDataInjector#copyProperties(List, StringMap)
093     */
094    StringMap injectContextData(final List<Property> properties, final StringMap reusable);
095
096    /**
097     * Returns a {@code ReadOnlyStringMap} object reflecting the current state of the context. Configuration properties
098     * are not included in the result.
099     * <p>
100     * This method may be called multiple times for each log event by Filters and Lookups and implementors should take
101     * care to make this method as performant as possible while preserving at least the following thread-safety
102     * guarantee.
103     * </p><p>
104     * Thread-safety note: The returned object can only be safely used <em>in the current thread</em>. Changes in the
105     * underlying context may or may not be reflected in the returned object, depending on the context data source and
106     * the implementation of this method. It is not safe to pass the returned object to another thread.
107     * </p>
108     * @return a {@code ReadOnlyStringMap} object reflecting the current state of the context, may not return {@code null}
109     */
110    ReadOnlyStringMap rawContextData();
111}