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.appender.rewrite;
    18
    19  import java.util.HashMap;
    20  import java.util.Map;
    21
    22  import org.apache.logging.log4j.Logger;
    23  import org.apache.logging.log4j.core.LogEvent;
    24  import org.apache.logging.log4j.core.config.plugins.Plugin;
    25  import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
    26  import org.apache.logging.log4j.core.config.plugins.PluginElement;
    27  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
    28  import org.apache.logging.log4j.core.impl.Log4jLogEvent;
    29  import org.apache.logging.log4j.core.util.KeyValuePair;
    30  import org.apache.logging.log4j.message.MapMessage;
    31  import org.apache.logging.log4j.message.Message;
    32  import org.apache.logging.log4j.status.StatusLogger;
    33
    34  /**
    35   * This policy modifies events by replacing or possibly adding keys and values to the MapMessage.
    36   */
    37  @Plugin(name = "MapRewritePolicy", category = "Core", elementType = "rewritePolicy", printObject = true)
    38  public final class MapRewritePolicy implements RewritePolicy {
    39      /**
    40       * Allow subclasses access to the status logger without creating another instance.
    41       */
    42      protected static final Logger LOGGER = StatusLogger.getLogger();
    43
    44      private final Map<String, String> map;
    45
    46      private final Mode mode;
    47
    48      private MapRewritePolicy(final Map<String, String> map, final Mode mode) {
    49          this.map = map;
    50          this.mode = mode;
    51      }
    52
    53      /**
    54       * Rewrite the event.
    55       * @param source a logging event that may be returned or
    56       * used to create a new logging event.
    57       * @return The LogEvent after rewriting.
    58       */
    59      @Override
    60      public LogEvent rewrite(final LogEvent source) {
    61          final Message msg = source.getMessage();
    62          if (msg == null || !(msg instanceof MapMessage)) {
    63              return source;
    64          }
    65
    66          final Map<String, String> newMap = new HashMap<String, String>(((MapMessage) msg).getData());
    67          switch (mode) {
    68              case Add: {
    69                  newMap.putAll(map);
    70                  break;
    71              }
    72              default: {
    73                  for (final Map.Entry<String, String> entry : map.entrySet()) {
    74                      if (newMap.containsKey(entry.getKey())) {
    75                          newMap.put(entry.getKey(), entry.getValue());
    76                      }
    77                  }
    78              }
    79          }
    80          final MapMessage message = ((MapMessage) msg).newInstance(newMap);
    81          if (source instanceof Log4jLogEvent) {
    82              final Log4jLogEvent event = (Log4jLogEvent) source;
    83              return Log4jLogEvent.createEvent(event.getLoggerName(), event.getMarker(), event.getLoggerFqcn(),
    84                  event.getLevel(), message, event.getThrown(), event.getThrownProxy(), event.getContextMap(),
    85                  event.getContextStack(), event.getThreadName(), event.getSource(), event.getTimeMillis());
    86          }
    87          return new Log4jLogEvent(source.getLoggerName(), source.getMarker(), source.getLoggerFqcn(), source.getLevel(),
    88              message, source.getThrown(), source.getContextMap(), source.getContextStack(), source.getThreadName(),
    89              source.getSource(), source.getTimeMillis());
    90      }
    91
    92      /**
    93       * An enumeration to identify whether keys not in the MapMessage should be added or whether only existing
    94       * keys should be updated.
    95       */
    96      public enum Mode {
    97          /**
    98           * Keys should be added.
    99           */
    100         Add,
    101         /**
    102          * Keys should be updated.
    103          */
    104         Update
    105     }
    106
    107     @Override
    108     public String toString() {
    109         final StringBuilder sb = new StringBuilder();
    110         sb.append("mode=").append(mode);
    111         sb.append(" {");
    112         boolean first = true;
    113         for (final Map.Entry<String, String> entry : map.entrySet()) {
    114             if (!first) {
    115                 sb.append(", ");
    116             }
    117             sb.append(entry.getKey()).append('=').append(entry.getValue());
    118             first = false;
    119         }
    120         sb.append('}');
    121         return sb.toString();
    122     }
    123
    124     /**
    125      * The factory method to create the MapRewritePolicy.
    126      * @param mode The string representation of the Mode.
    127      * @param pairs key/value pairs for the new Map keys and values.
    128      * @return The MapRewritePolicy.
    129      */
    130     @PluginFactory
    131     public static MapRewritePolicy createPolicy(
    132             @PluginAttribute("mode") final String mode,
    133             @PluginElement("KeyValuePair") final KeyValuePair[] pairs) {
    134         Mode op;
    135         if (mode == null) {
    136             op = Mode.Add;
    137         } else {
    138             op = Mode.valueOf(mode);
    139             if (op == null) {
    140                 LOGGER.error("Undefined mode " + mode);
    141                 return null;
    142             }
    143         }
    144         if (pairs == null || pairs.length == 0) {
    145             LOGGER.error("keys and values must be specified for the MapRewritePolicy");
    146             return null;
    147         }
    148         final Map<String, String> map = new HashMap<String, String>();
    149         for (final KeyValuePair pair : pairs) {
    150             final String key = pair.getKey();
    151             if (key == null) {
    152                 LOGGER.error("A null key is not valid in MapRewritePolicy");
    153                 continue;
    154             }
    155             final String value = pair.getValue();
    156             if (value == null) {
    157                 LOGGER.error("A null value for key " + key + " is not allowed in MapRewritePolicy");
    158                 continue;
    159             }
    160             map.put(pair.getKey(), pair.getValue());
    161         }
    162         if (map.isEmpty()) {
    163             LOGGER.error("MapRewritePolicy is not configured with any valid key value pairs");
    164             return null;
    165         }
    166         return new MapRewritePolicy(map, op);
    167     }
    168 }