Log4j2 Custom appender not identified in OSGi environment while using pax-logging 1.8.4

693 views
Skip to first unread message

Nipuni Perera

unread,
Feb 8, 2016, 1:53:17 AM2/8/16
to OPS4J
Hi,

I have written a custom appender extending the log4j2 AbstractAppender. But I am getting a runtime error[1]. While debug I could see that the log4j2 cannot load the new appender added to the osgi environment. (Issue did not appear when using log4j2.0.2 in non-osgi environment).

We were using pax-logging 1.8.4 (which exports log4j2 2.0.2) and the class loader cannot load the package (package read from the log4j2.xml configuration) as the new bundle is not visible to the pax-logging bundle.

I could resolve it after adding it(new appender) as a fragment to pax-logging-log4j2 1.8.4 [2]. (This way the new appender bundle became a fragment of pax-logging-log4j2 and visible to the class loader.)

Is this the proper way to add appenders in OSGi environment while using log4j2 with pax-logging? 

[1] ERROR Appenders contains an invalid element or attribute "HTTPSocket"
[2] <Fragment-Host>org.ops4j.pax.logging.pax-logging-log4j2</Fragment-Host>

Thanks,
Nipuni

Jean-Baptiste Onofré

unread,
Feb 8, 2016, 1:57:43 AM2/8/16
to OPS4J
Hi Nipuni,

I guess that you followed something like:

http://blog.nanthrax.net/2012/12/create-custom-log4j-appender-for-karaf-and-pax-logging/

Can you share your code ? HttpSocket attribute looks invalid.

Regards
JB

Nipuni Piyabasi Perera

unread,
Feb 8, 2016, 2:39:41 AM2/8/16
to op...@googlegroups.com
Hi Jean,

My code for new appender is as follows: (I have used plugin annotation and used pluginFactory method.)

/**
 * An Appender that delivers events over socket connections. Supports HTTP.
 */
@Plugin(name = "HTTPSocket", category = "Core", elementType = "appender", printObject = true)
public class HTTPSocketAppender extends AbstractOutputStreamAppender<AbstractSocketManager> {

    protected HTTPSocketAppender(String name, Layout<? extends Serializable> layout, Filter filter,
                                 boolean ignoreExceptions, boolean immediateFlush, AbstractSocketManager manager) {
        super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
    }

    @Override
    public void stop() {
        super.stop();
    }

    
    @PluginFactory
    public static HTTPSocketAppender createAppender(
            // @formatter:off
            @PluginAttribute("host") final String host,
            @PluginAttribute(value = "port", defaultInt = 0) final int port,
            @PluginAttribute(value = "connectTimeoutMillis", defaultInt = 0) final int connectTimeoutMillis,
            @PluginAttribute("name") final String name,
            @PluginAttribute(value = "immediateFlush", defaultBoolean = true) boolean immediateFlush,
            @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions,
            @PluginElement("Layout") Layout<? extends Serializable> layout,
            @PluginElement("Filter") final Filter filter) {
            // @formatter:on

        if (layout == null) {
            layout = SerializedLayout.createLayout();
        }

        if (name == null) {
            LOGGER.error("No name provided for HTTPAppender");
            return null;
        }
        immediateFlush = true;

        final AbstractSocketManager manager = createSocketManager(name, host, port, connectTimeoutMillis,
                layout);

        return new HTTPSocketAppender(name, layout, filter, ignoreExceptions, immediateFlush, manager);
    }

    /**
     * Creates an AbstractSocketManager.
     *
     * @throws IllegalArgumentException if the protocol cannot be handled.
     */
    protected static AbstractSocketManager createSocketManager(final String name, final String host,
                                                               final int port, final int connectTimeoutMillis, final Layout<? extends Serializable> layout) {

        return HTTPSocketManager.getSocketManager(host, port, connectTimeoutMillis, layout);
    }

I have added the above appeder in my log4j2.xml as: (I have added new appender package name in "packages" attribute in configuration element)

<Configuration status="INFO" packages="my.new.appender.package.name">
    <Appenders>
        ...
        <HTTPSocket name="HTTP_APPENDER" host="localhost" port="8080" connectTimeoutMillis="10000" immediateFlush="true" ignoreExceptions="true">
      <PatternLayout pattern="[%d] %5p {%c} [%hostname] - [%ip]- %m%ex%n"/>
    </HTTPSocket>
    </Appenders>
    <Loggers>
        <Root level="info">
            ...
        </Root>
        <Logger name="my.custom.package" additivity="true">
            <AppenderRef ref="HTTP_APPENDER"/>
        </Logger>
    </Loggers>
</Configuration>

Thanks,
Nipuni

--
--
------------------
OPS4J - http://www.ops4j.org - op...@googlegroups.com

---
You received this message because you are subscribed to a topic in the Google Groups "OPS4J" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ops4j/QvSOAmOrACg/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ops4j+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Nipuni Perera
Software Engineer; WSO2 Inc.; http://wso2.com
Email: nip...@wso2.com
Git hub profile: https://github.com/nipuni
Mobile: +94 (71) 5626680

Jean-Baptiste Onofré

unread,
Feb 8, 2016, 8:33:34 AM2/8/16
to OPS4J
Did you define your bundle in etc/startup.properties ?

It could be a race condition, where the log4j.xml is loaded before your appender is.

Regards
JB

Nipuni Piyabasi Perera

unread,
Feb 8, 2016, 8:52:55 AM2/8/16
to op...@googlegroups.com
Hi Jean,

No I haven't change any other file. I guess you are referring to Karaf environment. I am using Carbon-5 environment and we use Equinox. 

Thanks,
Nipuni
Reply all
Reply to author
Forward
0 new messages