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.filter;
    18
    19  import java.util.ArrayList;
    20  import java.util.HashMap;
    21  import java.util.List;
    22  import java.util.Map;
    23
    24  import org.apache.logging.log4j.Level;
    25  import org.apache.logging.log4j.Marker;
    26  import org.apache.logging.log4j.core.Filter;
    27  import org.apache.logging.log4j.core.LogEvent;
    28  import org.apache.logging.log4j.core.Logger;
    29  import org.apache.logging.log4j.core.config.Node;
    30  import org.apache.logging.log4j.core.config.plugins.Plugin;
    31  import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
    32  import org.apache.logging.log4j.core.config.plugins.PluginElement;
    33  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
    34  import org.apache.logging.log4j.core.util.KeyValuePair;
    35  import org.apache.logging.log4j.message.Message;
    36  import org.apache.logging.log4j.message.StructuredDataMessage;
    37
    38  /**
    39   * Filter based on data in a StructuredDataMessage.
    40   */
    41  @Plugin(name = "StructuredDataFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
    42  public final class StructuredDataFilter extends MapFilter {
    43
    44      private static final long serialVersionUID = 1L;
    45
    46      private StructuredDataFilter(final Map<String, List<String>> map, final boolean oper, final Result onMatch,
    47                                   final Result onMismatch) {
    48          super(map, oper, onMatch, onMismatch);
    49      }
    50
    51      @Override
    52      public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
    53                           final Throwable t) {
    54          if (msg instanceof StructuredDataMessage) {
    55              return filter((StructuredDataMessage) msg);
    56          }
    57          return Result.NEUTRAL;
    58      }
    59
    60      @Override
    61      public Result filter(final LogEvent event) {
    62          final Message msg = event.getMessage();
    63          if (msg instanceof StructuredDataMessage) {
    64              return filter((StructuredDataMessage) msg);
    65          }
    66          return super.filter(event);
    67      }
    68
    69      protected Result filter(final StructuredDataMessage message) {
    70          boolean match = false;
    71          for (final Map.Entry<String, List<String>> entry : getMap().entrySet()) {
    72              final String toMatch = getValue(message, entry.getKey());
    73              if (toMatch != null) {
    74                  match = entry.getValue().contains(toMatch);
    75              } else {
    76                  match = false;
    77              }
    78              if ((!isAnd() && match) || (isAnd() && !match)) {
    79                  break;
    80              }
    81          }
    82          return match ? onMatch : onMismatch;
    83      }
    84
    85      private String getValue(final StructuredDataMessage data, final String key) {
    86          if (key.equalsIgnoreCase("id")) {
    87              return data.getId().toString();
    88          } else if (key.equalsIgnoreCase("id.name")) {
    89              return data.getId().getName();
    90          } else if (key.equalsIgnoreCase("type")) {
    91              return data.getType();
    92          } else if (key.equalsIgnoreCase("message")) {
    93              return data.getFormattedMessage();
    94          } else {
    95              return data.getData().get(key);
    96          }
    97      }
    98
    99      /**
    100      * Create the StructuredDataFilter.
    101      * @param pairs Key and value pairs.
    102      * @param oper The operator to perform. If not "or" the operation will be an "and".
    103      * @param match The action to perform on a match.
    104      * @param mismatch The action to perform on a mismatch.
    105      * @return The StructuredDataFilter.
    106      */
    107     @PluginFactory
    108     public static StructuredDataFilter createFilter(
    109             @PluginElement("Pairs") final KeyValuePair[] pairs,
    110             @PluginAttribute("operator") final String oper,
    111             @PluginAttribute("onMatch") final Result match,
    112             @PluginAttribute("onMismatch") final Result mismatch) {
    113         if (pairs == null || pairs.length == 0) {
    114             LOGGER.error("keys and values must be specified for the StructuredDataFilter");
    115             return null;
    116         }
    117         final Map<String, List<String>> map = new HashMap<String, List<String>>();
    118         for (final KeyValuePair pair : pairs) {
    119             final String key = pair.getKey();
    120             if (key == null) {
    121                 LOGGER.error("A null key is not valid in MapFilter");
    122                 continue;
    123             }
    124             final String value = pair.getValue();
    125             if (value == null) {
    126                 LOGGER.error("A null value for key " + key + " is not allowed in MapFilter");
    127                 continue;
    128             }
    129             List<String> list = map.get(pair.getKey());
    130             if (list != null) {
    131                 list.add(value);
    132             } else {
    133                 list = new ArrayList<String>();
    134                 list.add(value);
    135                 map.put(pair.getKey(), list);
    136             }
    137         }
    138         if (map.isEmpty()) {
    139             LOGGER.error("StructuredDataFilter is not configured with any valid key value pairs");
    140             return null;
    141         }
    142         final boolean isAnd = oper == null || !oper.equalsIgnoreCase("or");
    143         return new StructuredDataFilter(map, isAnd, match, mismatch);
    144     }
    145 }