logging-log4j-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From <Alexander.Rat...@materna.de>
Subject Log4j2 Appender attributes with strict xml config
Date Mon, 14 Oct 2013 14:09:46 GMT
Hi,
I'm using log4j2-beta9 and want to configure it using a log4j2.xml in strict mode. My issue
is: how do I specify attributes that are not in the shipped schema file? An Example:
<?xml version="1.0" encoding="UTF-8" ?>
<Configuration
    status="DEBUG"
    strict="true"
    monitorInterval="5"
    name="TestingAttributes"
    verbose="true"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="Log4j-config.xsd">
    <Properties>
    </Properties>
    <Appenders>
        <Appender
            type="Console"
            name="SYSERR"
            target="SYSTEM_ERR"> <!-- cvc-complex-type.3.2.2: Attribute 'target' is
not allowed to appear in element 'Appender'. -->
            <Layout Type="PatternLayout">
                <Pattern>%date{dd.MM.yyyy HH:mm:ss,SSS} %5p %logger %m%n</Pattern>
            </Layout>
            <Filters>
                <Filter
                    type="MarkerFilter"
                    marker="FLOW"
                    onMatch="DENY"

                    onMismatch="NEUTRAL" />
                <Filter
                    type="MarkerFilter"
                    marker="EXCEPTION"
                    onMatch="DENY"
                    onMismatch="NEUTRAL" />
            </Filters>
        </Appender>
    </Appenders>
    <Loggers>
        <Root level="debug">
            <AppenderRef ref="SYSERR" />
        </Root>
    </Loggers>
</Configuration>
Notice that I want to set the appender to have the target SYSTEM_ERR but the attribute is
not allowed in strict mode.
target="SYSTEM_ERR"> <!-- cvc-complex-type.3.2.2: Attribute 'target' is not allowed
to appear in element 'Appender'. -->
I could always edit the Log4j-config.xsd and allow that attribute there but that would be
kind of wrong also because not all appenders have a target attribute.
As searching the web didn't help me so far, I'm asking you: Is there anything I'm missing
in configuring Log4j2 in strict XML mode?

I am for now using the following classes as a workaround:



    import org.apache.logging.log4j.core.config.*;

    import org.apache.logging.log4j.core.config.plugins.*;





    /**

     * Simple ConfigurationFactory that returns a {@link StrictXMLConfigurationFactory}

     *

     * @author <a href="mailto:Alexander.Rathai@Materna.DE">Alexander Rathai</a>

     */

    @Plugin(name = "StrictXMLConfigurationFactory", category = "ConfigurationFactory")

    @Order(4)

    public class StrictXMLConfigurationFactory extends ConfigurationFactory {



            /**

             * Valid file extensions for XML files.

             */

            public static final String[] SUFFIXES = new String[]{".xml"};





            /**

             * @see org.apache.logging.log4j.core.config.ConfigurationFactory#getConfiguration(org.apache.logging.log4j.core.config.ConfigurationFactory.ConfigurationSource)

             */

            @Override

            public Configuration getConfiguration(ConfigurationSource source) {

                    return new StrictXMLConfiguration(source);

            }





            /**

             * @see org.apache.logging.log4j.core.config.ConfigurationFactory#getSupportedTypes()

             */

            @Override

            public String[] getSupportedTypes() {

                    return XMLConfigurationFactory.SUFFIXES;

            }

    }



And



    import java.util.*;



    import org.apache.logging.log4j.core.config.*;

    import org.apache.logging.log4j.core.config.ConfigurationFactory.ConfigurationSource;





    /**

     * Lets the base class {@link XMLConfiguration} do all the hard work and patch the object
tree before it is being used by {@link BaseConfiguration}

     *

     * @author <a href="mailto:Alexander.Rathai@Materna.DE">Alexander Rathai</a>

     */

    public class StrictXMLConfiguration extends XMLConfiguration {



            /**

             * @param configSource

             */

            public StrictXMLConfiguration(ConfigurationSource configSource) {

                    super(configSource);

            }





            /**

             * @see org.apache.logging.log4j.core.config.XMLConfiguration#setup()

             */

            @Override

            public void setup() {

                    super.setup();

                    alterHierarchy(this.rootNode);

            }





            /**

             * Recourses the object tree and puts replaces KeyValuePairs as attributes in
the parent object

             *

             * @param node the node to alter

             */

            private void alterHierarchy(final Node node) {

                    final List<Node> children = node.getChildren();

    //                final ArrayList<Node> usedChilds = new ArrayList<>();

                    Map<String, String> attributes = node.getAttributes();

                    for( Node child : children ) {

                            if( "KeyValuePair".equalsIgnoreCase(child.getName()) ) {

                                    String key = child.getAttributes().get("key");

                                    String value = child.getValue();

                                    attributes.put(key, value);

    //                                usedChilds.add(child);

                            }

                            else {

                                    alterHierarchy(child);

                            }

                    }

    //                children.removeAll(usedChilds);

            }

    }



And i patched the xsd a bit:



    <?xml version="1.0" encoding="UTF-8"?>

    <!--

     Licensed to the Apache Software Foundation (ASF) under one or more

     contributor license agreements.  See the NOTICE file distributed with

     this work for additional information regarding copyright ownership.

     The ASF licenses this file to You under the Apache License, Version 2.0

     (the "License"); you may not use this file except in compliance with

     the License.  You may obtain a copy of the License at



          http://www.apache.org/licenses/LICENSE-2.0



     Unless required by applicable law or agreed to in writing, software

     distributed under the License is distributed on an "AS IS" BASIS,

     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

     See the License for the specific language governing permissions and

     limitations under the License.



     Altered by <a href="mailto:Alexander.Rathai@Materna.DE">Alexander Rathai</a>:

     Tweaked minOccurs maxOccurs and some other things

     Allowed KeyValuePairType to appear inside AppenderType



    -->

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
attributeFormDefault="unqualified">

        <xs:element name="Configuration" type="ConfigurationType"/>

        <xs:complexType name="ConfigurationType">

            <xs:sequence>

                <xs:element name="Properties" type="PropertiesType" minOccurs="0"/>

                <xs:choice minOccurs="0" maxOccurs="1">

                    <xs:element name="Filters" type="FiltersType"/>

                    <xs:element name="Filter" type="FilterType"/>

                </xs:choice>

                <xs:element name="ThresholdFilter" type="ThresholdFilterType" minOccurs="0"/>

                <xs:element name="Appenders" type="AppendersType"/>

                <xs:element name="Loggers" type="LoggersType"/>

            </xs:sequence>

            <xs:attribute name="dest" type="xs:string"/>

            <xs:attribute name="advertiser" type="xs:string"/>

            <xs:attribute name="monitorInterval" type="xs:int"/>

            <xs:attribute name="name" type="xs:string"/>

            <xs:attribute name="packages" type="xs:string"/>

            <xs:attribute name="schema" type="xs:string"/>

            <xs:attribute name="shutdownHook" type="xs:boolean"/>

            <xs:attribute name="status" type="xs:string"/>

            <xs:attribute name="strict" type="xs:string"/>

            <xs:attribute name="verbose" type="xs:boolean"/>

        </xs:complexType>

        <xs:complexType name="PropertiesType">

            <xs:sequence>

                <xs:element name="Property" type="PropertyType" minOccurs="1" maxOccurs="unbounded"/>

            </xs:sequence>

        </xs:complexType>

        <xs:complexType name="AppenderType">

            <xs:sequence>

                <xs:element name="KeyValuePair" type="KeyValuePairType" minOccurs="0" maxOccurs="unbounded"/>

                <xs:element name="Layout" type="LayoutType" minOccurs="0"/>

                <xs:choice minOccurs="0" maxOccurs="1">

                    <xs:element name="Filters" type="FiltersType"/>

                    <xs:element name="Filter" type="FilterType"/>

                </xs:choice>

            </xs:sequence>

            <xs:attribute name="type" type="xs:string" use="required"/>

            <xs:attribute name="name" type="xs:string" use="required"/>

            <xs:attribute name="fileName" type="xs:string" use="optional"/>

        </xs:complexType>

        <xs:complexType name="RootType">

            <xs:sequence>

                <xs:element name="AppenderRef" type="AppenderRefType" minOccurs="1" maxOccurs="unbounded"/>

            </xs:sequence>

            <xs:attribute name="level" type="xs:string"/>

        </xs:complexType>

        <xs:complexType name="PropertyType">

            <xs:simpleContent>

                <xs:extension base="xs:string">

                    <xs:attribute name="name" type="xs:string"/>

                </xs:extension>

            </xs:simpleContent>

        </xs:complexType>

        <xs:complexType name="KeyValuePairType">

            <xs:simpleContent>

                <xs:extension base="xs:string">

                    <xs:attribute name="key" type="xs:string"/>

                    <xs:attribute name="value" type="xs:string"/>

                </xs:extension>

            </xs:simpleContent>

        </xs:complexType>

        <xs:complexType name="AppendersType">

            <xs:sequence>

                <xs:element name="Appender" type="AppenderType" minOccurs="1" maxOccurs="unbounded"/>

            </xs:sequence>

        </xs:complexType>

        <xs:complexType name="AppenderRefType">

            <xs:simpleContent>

                <xs:extension base="xs:string">

                    <xs:attribute name="ref" type="xs:string" use="required"/>

                </xs:extension>

            </xs:simpleContent>

        </xs:complexType>

        <xs:complexType name="LoggerType">

            <xs:sequence>

                <xs:choice minOccurs="0" maxOccurs="1">

                    <xs:element name="Filters" type="FiltersType"/>

                    <xs:element name="Filter" type="FilterType"/>

                </xs:choice>

                <xs:element name="AppenderRef" type="AppenderRefType"/>

            </xs:sequence>

            <xs:attribute name="name" type="xs:string" use="required"/>

            <xs:attribute name="level" type="xs:string" use="optional"/>

            <xs:attribute name="additivity" type="xs:string" use="optional"/>

        </xs:complexType>

        <xs:complexType name="FilterType" mixed="true">

            <xs:sequence>

                <xs:element name="KeyValuePair" type="KeyValuePairType" minOccurs="0"/>

            </xs:sequence>

            <xs:attribute name="type" type="xs:string" use="required"/>

            <xs:attribute name="level" type="xs:string" use="optional"/>

            <xs:attribute name="marker" type="xs:string" use="optional"/>

            <xs:attribute name="onMatch" type="xs:string" use="optional"/>

            <xs:attribute name="onMismatch" type="xs:string" use="optional"/>

        </xs:complexType>

        <xs:complexType name="FiltersType">

            <xs:sequence>

                <xs:element name="Filter" type="FilterType" minOccurs="0" maxOccurs="unbounded"/>

            </xs:sequence>

        </xs:complexType>

        <xs:complexType name="LoggersType" mixed="true">

            <xs:sequence>

                <xs:element name="Logger" type="LoggerType" minOccurs="0" maxOccurs="unbounded"/>

                <xs:element name="Root" type="RootType" minOccurs="1" maxOccurs="1"/>

            </xs:sequence>

        </xs:complexType>

        <xs:complexType name="LayoutType" mixed="true">

            <xs:sequence>

                <xs:element name="Pattern" type="xs:string" minOccurs="0"/>

            </xs:sequence>

            <xs:attribute name="Type" type="xs:string" use="required"/>

            <xs:attribute name="Pattern" type="xs:string" use="optional"/>

        </xs:complexType>

        <xs:complexType name="ThresholdFilterType">

            <xs:attribute name="level" type="xs:string" use="optional"/>

            <xs:attribute name="onMatch" type="xs:string" use="optional"/>

            <xs:attribute name="onMismatch" type="xs:string" use="optional"/>

        </xs:complexType>

    </xs:schema>



Then I set the Systemproperty `log4j.configurationFactory` to the fully qualified classname
of the StrictXMLConfigurationFactory and it works really well!

Best Regards,
Alex

Alexander Rathai
___________________________________________
MATERNA GmbH Information & Communications
Voßkuhle 37 * 44141 Dortmund * Germany
Amtsgericht Dortmund * HRB 5839
Geschäftsführer: Dr. Winfried Materna, Helmut an de Meulen, Ralph Hartwig
Tel: +49 (231) 5599-8622
http://www.materna.de<http://www.materna.de/>


Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message