View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core;
18  
19  import java.util.List;
20  
21  import org.apache.logging.log4j.core.config.Property;
22  import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
23  import org.apache.logging.log4j.core.impl.ThreadContextDataInjector;
24  import org.apache.logging.log4j.util.ReadOnlyStringMap;
25  import org.apache.logging.log4j.util.StringMap;
26  
27  /**
28   * Responsible for initializing the context data of LogEvents. Context data is data that is set by the application to be
29   * included in all subsequent log events.
30   * <p><b>NOTE: It is no longer recommended that custom implementations of this interface be provided as it is
31   * difficult to do. Instead, provide a custom ContextDataProvider.</b></p>
32   * <p>
33   * <p>
34   * The source of the context data is implementation-specific. The default source for context data is the ThreadContext.
35   * </p><p>
36   * In some asynchronous models, work may be delegated to several threads, while conceptually this work shares the same
37   * context. In such models, storing context data in {@code ThreadLocal} variables is not convenient or desirable.
38   * Users can configure the {@code ContextDataInjectorFactory} to provide custom {@code ContextDataInjector} objects,
39   * in order to initialize log events with context data from any arbitrary context.
40   * </p><p>
41   * When providing a custom {@code ContextDataInjector}, be aware that the {@code ContextDataInjectorFactory} may be
42   * invoked multiple times and the various components in Log4j that need access to context data may each have their own
43   * instance of {@code ContextDataInjector}.
44   * This includes the object(s) that populate log events, but also various lookups and filters that look at
45   * context data to determine whether an event should be logged.
46   * </p><p>
47   * Implementors should take particular note of how the different methods in the interface have different thread-safety
48   * guarantees to enable optimal performance.
49   * </p>
50   *
51   * @see StringMap
52   * @see ReadOnlyStringMap
53   * @see ContextDataInjectorFactory
54   * @see org.apache.logging.log4j.ThreadContext
55   * @see ThreadContextDataInjector
56   * @since 2.7
57   */
58  public interface ContextDataInjector {
59      /**
60       * Returns a {@code StringMap} object initialized with the specified properties and the appropriate
61       * context data. The returned value may be the specified parameter or a different object.
62       * <p>
63       * This method will be called for each log event to initialize its context data and implementors should take
64       * care to make this method as performant as possible while preserving at least the following thread-safety
65       * guarantee.
66       * </p><p>
67       * Thread-safety note: The returned object can safely be passed off to another thread: future changes in the
68       * underlying context data will not be reflected in the returned object.
69       * </p><p>
70       * Example implementation:
71       * </p>
72       * <pre>
73       * public StringMap injectContextData(List<Property> properties, StringMap reusable) {
74       *     if (properties == null || properties.isEmpty()) {
75       *         // assume context data is stored in a copy-on-write data structure that is safe to pass to another thread
76       *         return (StringMap) rawContextData();
77       *     }
78       *     // first copy configuration properties into the result
79       *     ThreadContextDataInjector.copyProperties(properties, reusable);
80       *
81       *     // then copy context data key-value pairs (may overwrite configuration properties)
82       *     reusable.putAll(rawContextData());
83       *     return reusable;
84       * }
85       * </pre>
86       *
87       * @param properties Properties from the log4j configuration to be added to the resulting ReadOnlyStringMap. May be
88       *          {@code null} or empty
89       * @param reusable a {@code StringMap} instance that may be reused to avoid creating temporary objects
90       * @return a {@code StringMap} instance initialized with the specified properties and the appropriate
91       *          context data. The returned value may be the specified parameter or a different object.
92       * @see ThreadContextDataInjector#copyProperties(List, StringMap)
93       */
94      StringMap injectContextData(final List<Property> properties, final StringMap reusable);
95  
96      /**
97       * Returns a {@code ReadOnlyStringMap} object reflecting the current state of the context. Configuration properties
98       * are not included in the result.
99       * <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 }