• 聊聊logback的MarkerFilter


    本文主要研究一下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);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    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.
         * 
         * 

    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; } }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    MarkerFactory通过static方法来初始化MARKER_FACTORY,若SLF4JServiceProvider不为null则取provider.getMarkerFactory(),否则取BasicMarkerFactory

    BasicMarkerFactory

    org/slf4j/helpers/BasicMarkerFactory.java

    public class BasicMarkerFactory implements IMarkerFactory {
    
        private final ConcurrentMap markerMap = new ConcurrentHashMap<>();
    
        /**
         * Regular users should not create
         * BasicMarkerFactory instances. Marker
         * 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);
        }
    
        public Marker getDetachedMarker(String name) {
            return new BasicMarker(name);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    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.
         *
         * 

    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. *

    * * @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 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(); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106

    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 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 potential 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 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 it = this.iterator();
            Marker reference;
            StringBuilder 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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132

    BasicMarker实现了Marker接口,它定义了一个CopyOnWriteArrayList类型的referenceList

    示例

    配置

    
    
    
    
      
        username
        sebastien
        ACCEPT
      
    
      
        billing
        DENY
      
    
      
        
          %date [%thread] %-5level %logger - %msg%n
        
      
    
      
        
      
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    使用

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

    小结

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

  • 相关阅读:
    测试面试题集锦(四)| Linux 与 Python 编程篇(附答案)
    Websocket实现方式二——注解方式
    uniapp v3+ts 使用 u-upload上传图片以及视频
    微信小程序接入火山引擎埋点数据
    第二章 模型评估与选择(下)
    vue-cil之elementui、vuex(任务管理器)
    面向对象编程在Perl中的实现:解锁Perl的OOP潜力
    线性代数学习笔记10-3:左右逆、伪逆(从四个子空间和SVD角度理解)
    tqdm python使用总结
    QGraphicsView,QGraphicsScene和QGraphicsItem
  • 原文地址:https://blog.csdn.net/hello_ejb3/article/details/134433516