开发者

logback标记日志过滤器MarkerFilter源码解读

目录
  • MarkerFilter
  • MarkerFactory
    • BasicMarkerFactory
  • Marker
    • BasicMarker
  • 示例
    • 配置
    • 使用
  • 小结

    本文主要研究一下logback的MarkerFilter

    MarkerFilter

    ch/qos/logback/classic/turbo/MarkerFilter.Java

    public class MarkerFilter extends MatchingFilter {
        Marker markerToMatch;
        @Override
        public void start() {
            if (markerToMatch != null) {
                super.start();
            } else {
                addError("The marker property must be set for [" + getName() + "]");
            }
        }
        @Override
        public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) {
            if (!isStarted()) {
                return FilterReply.NEUTRAL;
            }
            if (marker == null) {
                return onMismatch;
            }
            if (marker.contains(markerToMatch)) {
                return onMatch;
            } else {
                return onMismatch;
            }
        }
        /**
         * The marker to match in the event.
         * 
         * @param markerStr
         */
        public void setMarker(String markerStr) {
            if (markerStr != null) {
                this.markerToMatch = MarkerFactory.getMarker(markerStr);
            }
        }
    }
    MarkerFilter定义了markerToMatch属性,其decide方法对于传入的marker为null返回onMismatch,对于包含markerToMatch的返回onMatch,否则返回onMismatch

    MarkerFactory

    org/slf4j/MarkerFactory.java

    public class MarkerFactory {
        static IMarkerFactory MARKER_FACTORY;
        private MarkerFactory() {
        }
        // this is where the binding happens
        static {
            SLF4jserviceProvider provider = LoggerFactory.getProvider();
            if (provider != null) {
                MARKER_FACTORY = provider.getMarkerFactory();
            } else {
                Util.report("Failed to find provider");
                Util.report("Defaulting to BasicMarkerFactory.");
                MARKER_FACTORY = new BasicMarkerFactory();
            }
        }
        /**
         * Return a Marker instance as specified by the name parameter using the
         * previously bound {@link IMarkerFactory}instance.
         * 
         * @param name
         *          The name of the {@link Marker} object to return.
         * @return marker
         */
        public static Marker getMarker(String name) {
            return MARKER_FACTORY.getMarker(name);
        }
        /**
         * Create a marker which is detached (even at birth) from the MarkerFactory.
         *
         * @param name the name of the marker
         * @return a dangling marker
         * @since 1.5.1
         */
        public static Marker getDetachedMarker(String name) {
            return MARKER_FACTORY.getDetachedMarker(name);
        }
        /**
         * Return the {@link IMarkerFactory}instance in use.
         * 
         * <p>The IMarkerFactory instance is usually bound with this class at 
         * compile time.
         * 
         * @return the IMarkerFactory instance in use
         */
        public static IMarkerFactory getIMarkerFactory() {
            return MARKER_FACTORY;
        }
    }
    MarkerFactory通过static方法来初始化MARKER_FACTORY,若SLF4JServiceProvider不为null则取provider.getMarkerFactory(),否则取BasicMarkerFactory

    BasicMarkerFactory

    org/slf4j/helpers/BasicMarkerFactory.java

    public class BasicMarkerFactory implements IMarkerFactory {
        private final ConcurrentMap<String, Marker> markerMap = new ConcurrentHashMap<>();
        /**
         * Regular users should <em>not</em> create
         * <code>BasicMarkerFactory</code> instances. <code>Marker</code>
         * instances can be obtained using the static {@link
         * org.slf4j.MarkerFactory#getMarker} method.
         */
        public BasicMarkerFactory() {
        }
        /**
         * Manufacture a {@link BasicMarker} instance by name. If the instance has been 
         * created earlier, return the previously created instance. 
         * 
         * @param name the name of the marker to be created
         * @return a Marker instance
         */
        public Marker getMarker(String name) {
            if (name == null) {
                throw new IllegalArgumentException("Marker name cannot be null");
            }
            Marker marker = markerMap.get(name);
            if (marker == null) {
                marker = new BasicMarker(name);
                Marker oldMarker = markerMap.putIfAbsent(name, marker);编程客栈
                if (oldMarker != null) {
                    marker = oldMarker;
                }
            }
            return marker;
        }
        /**
         * Does the name marked already exist?
         */
        public boolean exists(String name) {
            if (name == null) {
                return false;
            }
            return markerMap.containsKey(name);
        }
        public boolean detachMarker(String name) {
            if (name == null) {
                return false;
            }
            return (markerMap.remove(name) != null);
        }
        publjavascriptic Marker getDetachedMarker(String name) {
            return new BasicMarker(name);
        }
    }
    BasicMarkerFactory通过ConcurrentMap来存储string与Marker的映射,创建的是BasicMarker

    Marker

    org/slf4j/Marker.java

    public interface Marker extends Serializable {
        /**
         * This constant represents any marker, including a null marker.
         */
        public final String ANY_MARKER = "*";
        /**
         * This constant represents any non-null marker.
         */
        public final String ANY_NON_NULL_MARKER = "+";
        /**
         * Get the name of this Marker.
         * 
         * @return name of marker
         */
        public String getName();
        /**
         * Add a reference to another Marker.
         *
         * <p>Note that the fluent API allows adding multiple markers to a logging statement.
         * It is often preferable to use multiple markers instead of nested markers.
         * </p>
         *
         * @param reference
         *                a reference to another marker
         * @throws IllegalArgumentException
         *                 if 'reference' is null
         */
        public void add(Marker reference);
        /**
         * Remove a marker reference.
         * 
         * @param reference
         *                the marker reference to remove
         * @return true if reference could be found and removed, false otherwise.
         */
        public boolean remove(Marker reference);
        /**
         * @deprecated Replaced by {@link #hasReferences()}.
         */
        @Deprecated
        public boolean hasChildren();
        /**
         * Does this marker have any references?
         * 
         * @return true if this marker has one or more references, false otherwise.
         */
        public boolean hasReferences();
        /**
         * Returns an Iterator which can be used to iterate over the references of this
         * marker. An empty iterator is returned when this marker has no references.
         * 
         * @return Iterator over the references of this marker
         */
        public Iterator<Marker> iterator();
        /**
         * Does this marker contain a reference to the 'other' marker? Marker A is defined 
         * to contain marker B, if A == B or if B is referenced by A, or if B is referenced
         * by any one of A's references (recursively).
         * 
         * @param other
         *                The marker to test for inclusion.
         * @throws IllegalArgumentException
         *                 if 'other' is null
         * @return Whether this marker contains the other marker.
         */
        public boolean contains(Marker other);
        /**
         * Does this marker contain the marker named 'name'?
         * 
         * If 'name' is null the returned value is always false.
         * 
         * @param name The marker name to test for inclusion.
         * @return Whether this marker contains the other marker.
         */
        public boolean contains(String name);
        /**
         * Markers are considered equal if they have the same name.
         *
         * @param o
         * @return true, if this.name equals o.name
         *
         * @since 1.5.1
         */
        public boolean equals(Object o);
        /**
         * Compute the hash code based on the name of this marker.
         * Note that markers are considered equal if they have the same name.
         * 
         * @return the computed hashCode
         * @since 1.5.1
         */
        public int hashCode();
    }
    Marker接口定义了getName、add、remove、hasReferences、iterator、contains、equals、hashCode方法

    BasicMarker

    org/slf4j/helpers/BasicMarker.java

    public class BasicMarker implements Marker {
        private static final long serialVersionUID = -2849567615646933777L;
        private final String name;
        private final List<Marker> referenceList = new CopyOnWriteArrayList<>();
        BasicMarker(String name) {
            if (name == null) {
                throw new IllegalArgumentException("A marker name cannot be null");
            }
            this.name = name;
        }
        public String getName() {
            return name;
        }
        public void add(Marker reference) {
            if (reference == null) {
                throw new IllegalArgumentException("A null value cannot be added to a Marker as reference.");
            }
            // no point in adding the reference multiple times
            if (this.contains(reference)) {
                return;
            } else if (reference.contains(this)) { // avoid recursion
                // a poteKECMRLqntial reference should not hold its future "parent" as a reference
                return;
            } else {
                referenceList.add(reference);
            }
        }
        public boolean hasReferences() {
            return (referenceList.size() > 0);
        }
        @Deprecated
        public boolean hasChildren() {
            return hasReferences();
        }
        public Iterator<Marker> iterator() {
            return referenceList.iterator();
        }
        public boolean remove(Marker referenceToRemove) {
            return referenceList.remove(referenceToRemove);
        }
        public boolean contains(Marker other) {
            if (other == null) {
                throw new IllegalArgumentException("Other cannot be null");
            }
            if (this.equals(other)) {
                return true;
            }
            if (hasReferences()) {
                for (Marker ref : referenceList) {
                    if (ref.contains(other)) {
                        return true;
                    }
                }
            }
            return false;
        }
        /**
         * This method is mainly used with Expression EvaLuators.
         */
        public boolean contains(String name) {
            if (name == null) {
                throw new IllegalArgumentException("Other cannot be null");
            }
            if (this.name.equals(name)) {
                return true;
            }
            if (hasReferences()) {
                for (Marker ref : referenceList) {
                    if (ref.contains(name)) {
                        return true;
                    }
                }
            }
            return false;
        }
        private static final String OPEN = "[ ";
        private static final String CLOSE = " ]";
        private static final String SEP = ", ";
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (!(obj instanceof Marker))
                return false;
            final Marker other = (Marker) obj;
            return name.equals(other.getName());
        }
        public int hashCode() {
            return name.hashCode();
        }
        public String toString() {
            if (!this.hasReferences()) {
                return this.getName();
            }
            Iterator<Marker> it = this.iterator();
            Marker reference;
            StringjavascriptBuilder sb = new StringBuilder(this.getName());
            sb.append(' ').append(OPEN);
            while (it.hasNext()) {
                reference = it.next();
                sb.append(reference.getName());
                if (it.hasNext()) {
                    sb.append(SEP);
                }
            }
            sb.append(CLOSE);
            return sb.toString();
        }
    }
    BasicMarker实现了Marker接口,它定义了一个CopyOnWriteArrayList类型的referenceList

    示例

    配置

    <?XML version="1.0" encoding="UTF-8" ?>
    <configuration>
      <turboFilter class="ch.qos.logback.classic.turbo.MDCFilter">
        <MDCKey>username</MDCKey>
        <Value>sebastien</Value>
        <OnMatch>ACCEPT</OnMatch>
      </turboFilter>
      <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
        <Marker>billing</Marker>
        <OnMatch>DENY</OnMatch>
      </turboFilter>
      <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
          <Pattern>%date [%thread] %-5level %logger - %msg%n</Pattern>
        </layout>
      </appender>
      <root level="info">
        <appender-ref ref="console" />
      </root>
    </confi编程客栈guration>

    使用

    Marker billing = MarkerFactory.getMarker("billing");
    logger.error(billing, "billing statement {}", i);

    小结

    logback提供了MarkerFilter来支持slf4j的Marker,可以通过MarkerFactory.getMarker获取marker,然后在logger中使用,而配置文件可以配置MarkerFilter,设置指定的marker的onMatch或者onMismatch行为。

    以上就是logback标记日志过滤器MarkerFilter源码解读的详细内容,更多关于logback MarkerFilter的资料请关注编程客栈(www.devze.com)其它相关文章!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜