Done.

On Thu, May 4, 2017 at 5:16 PM, Matt Sicker <boa...@gmail.com> wrote:

> As long as the plugin configuration that's exposed doesn't leak any
> internal details specific to HttpURLConnection, I think we'll be fine as
> you say. I haven't looked closely at the code yet, though (working hours
> for me right now), so I don't have specific suggestions yet.
>
> On 4 May 2017 at 10:15, Mikael Ståldal <mikael.stal...@magine.com> wrote:
>
> > I would say that the HttpManager would be that facade. If you want
> another
> > implementation you write another HttpManager and add support for
> selecting
> > between different managers in HttpAppender. I don't think that much code
> in
> > HttpManager can be shared between different implementations.
> >
> > Maybe we should rename HttpManager to HttpURLConnectionManager?
> >
> > On Thu, May 4, 2017 at 5:12 PM, Matt Sicker <boa...@gmail.com> wrote:
> >
> > > Depends on the use case. Using HttpURLConnection covers a lot of them,
> > but
> > > users may need more customization to handle their requests. I'm not so
> > sure
> > > how necessary it is to support in an initial version, but abstracting
> the
> > > use of HttpURLConnection behind a facade would be handy for future
> > > extensions.
> > >
> > > On 4 May 2017 at 10:03, Mikael Ståldal <mikael.stal...@magine.com>
> > wrote:
> > >
> > > > Yes, but what benefits would the more advanced client bring us?
> > > >
> > > > On Thu, May 4, 2017 at 4:59 PM, Matt Sicker <boa...@gmail.com>
> wrote:
> > > >
> > > > > The main thing I wanted regarding plugability of clients was to
> allow
> > > for
> > > > > both java.net usage along with a more advanced client. It could be
> > > > > simplified down to only allowing one non-java.net client library.
> > > > >
> > > > > I don't want to have two HTTP plugins with different configurations
> > and
> > > > > other confusion just to support java.net and a dependency version.
> > > > >
> > > > > On 4 May 2017 at 09:55, Mikael Ståldal <mikael.stal...@magine.com>
> > > > wrote:
> > > > >
> > > > > > I can see advantages in using Netty-http or similar to use async
> > NIO,
> > > > > > though those advantages will be a bit limited as long as we don't
> > > have
> > > > a
> > > > > > proper interface for async appenders (LOG4J2-1797
> > > > > > <https://issues.apache.org/jira/browse/LOG4J2-1797>).
> > > > > >
> > > > > > But are there any significant advantages in using another
> > synchronous
> > > > > HTTP
> > > > > > client library?
> > > > > >
> > > > > > Given that an appender is a plugin by itself, I am a bit
> skeptical
> > to
> > > > > > adding another layer of pluggability unless there are are
> > significant
> > > > > > advantages with another library and we can share significant
> amount
> > > of
> > > > > code
> > > > > > between different implementations.
> > > > > >
> > > > > > On Thu, May 4, 2017 at 4:42 PM, Matt Sicker <boa...@gmail.com>
> > > wrote:
> > > > > >
> > > > > > > Thanks for starting this! My idea in mind when I wrote the
> ticket
> > > was
> > > > > to
> > > > > > > make the actual client pluggable so that users could use
> > > > > > HttpURLConnection
> > > > > > > (no dependencies), Apache HttpClient, Netty-HTTP, etc.
> > > > > > >
> > > > > > > On 4 May 2017 at 07:49, <mi...@apache.org> wrote:
> > > > > > >
> > > > > > > > Repository: logging-log4j2
> > > > > > > > Updated Branches:
> > > > > > > >   refs/heads/LOG4J2-1442 [created] 0af515f3b
> > > > > > > >
> > > > > > > >
> > > > > > > > LOG4J2-1442 Generic HTTP appender
> > > > > > > >
> > > > > > > >
> > > > > > > > Project: http://git-wip-us.apache.org/
> > > > repos/asf/logging-log4j2/repo
> > > > > > > > Commit: http://git-wip-us.apache.org/
> repos/asf/logging-log4j2/
> > > > > > > > commit/410f9d36
> > > > > > > > Tree: http://git-wip-us.apache.org/
> > > repos/asf/logging-log4j2/tree/
> > > > > > > 410f9d36
> > > > > > > > Diff: http://git-wip-us.apache.org/
> > > repos/asf/logging-log4j2/diff/
> > > > > > > 410f9d36
> > > > > > > >
> > > > > > > > Branch: refs/heads/LOG4J2-1442
> > > > > > > > Commit: 410f9d360eabcdc6949c75973b786c9e2cec9c66
> > > > > > > > Parents: 8852cd1
> > > > > > > > Author: Mikael Ståldal <mikael.stal...@magine.com>
> > > > > > > > Authored: Thu May 4 14:21:59 2017 +0200
> > > > > > > > Committer: Mikael Ståldal <mikael.stal...@magine.com>
> > > > > > > > Committed: Thu May 4 14:45:04 2017 +0200
> > > > > > > >
> > > > > > > > ------------------------------------------------------------
> > > > > ----------
> > > > > > > >  .../log4j/core/appender/HttpAppender.java       | 161
> > > > > > > +++++++++++++++++++
> > > > > > > >  .../log4j/core/appender/HttpManager.java        |  82
> > > ++++++++++
> > > > > > > >  .../log4j/core/appender/HttpAppenderTest.java   |  52
> ++++++
> > > > > > > >  .../src/test/resources/HttpAppenderTest.xml     |  43 +++++
> > > > > > > >  src/changes/changes.xml                         |   3 +
> > > > > > > >  src/site/site.xml                               |   1 +
> > > > > > > >  src/site/xdoc/manual/appenders.xml              |  78
> > +++++++++
> > > > > > > >  7 files changed, 420 insertions(+)
> > > > > > > > ------------------------------------------------------------
> > > > > ----------
> > > > > > > >
> > > > > > > >
> > > > > > > > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/
> > > > > > > > 410f9d36/log4j-core/src/main/java/org/apache/logging/log4j/
> > > > > > > > core/appender/HttpAppender.java
> > > > > > > > ------------------------------------------------------------
> > > > > ----------
> > > > > > > > diff --git a/log4j-core/src/main/java/
> > > > org/apache/logging/log4j/core/
> > > > > > > appender/HttpAppender.java
> > > > > > > > b/log4j-core/src/main/java/org/apache/logging/log4j/core/
> > > > > > > > appender/HttpAppender.java
> > > > > > > > new file mode 100644
> > > > > > > > index 0000000..e0f1b27
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/log4j-core/src/main/java/
> org/apache/logging/log4j/core/
> > > > > > > > appender/HttpAppender.java
> > > > > > > > @@ -0,0 +1,161 @@
> > > > > > > > +/*
> > > > > > > > + * 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.
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +package org.apache.logging.log4j.core.appender;
> > > > > > > > +
> > > > > > > > +import java.io.IOException;
> > > > > > > > +import java.io.Serializable;
> > > > > > > > +import java.util.Objects;
> > > > > > > > +import java.util.concurrent.TimeUnit;
> > > > > > > > +
> > > > > > > > +import org.apache.logging.log4j.core.Appender;
> > > > > > > > +import org.apache.logging.log4j.core.Filter;
> > > > > > > > +import org.apache.logging.log4j.core.Layout;
> > > > > > > > +import org.apache.logging.log4j.core.LogEvent;
> > > > > > > > +import org.apache.logging.log4j.core.config.Node;
> > > > > > > > +import org.apache.logging.log4j.core.config.Property;
> > > > > > > > +import org.apache.logging.log4j.core.config.plugins.Plugin;
> > > > > > > > +import org.apache.logging.log4j.core.config.plugins.
> > > > > > > > PluginBuilderAttribute;
> > > > > > > > +import org.apache.logging.log4j.core.config.plugins.
> > > > > > > PluginBuilderFactory;
> > > > > > > > +import org.apache.logging.log4j.core.
> > > > config.plugins.PluginElement;
> > > > > > > > +import org.apache.logging.log4j.core.
> > config.plugins.validation.
> > > > > > > > constraints.Required;
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + * Sends log events over HTTP.
> > > > > > > > + */
> > > > > > > > +@Plugin(name = "Http", category = Node.CATEGORY,
> elementType =
> > > > > > > > Appender.ELEMENT_TYPE, printObject = true)
> > > > > > > > +public final class HttpAppender extends AbstractAppender {
> > > > > > > > +
> > > > > > > > +    /**
> > > > > > > > +     * Builds HttpAppender instances.
> > > > > > > > +     * @param <B> The type to build
> > > > > > > > +     */
> > > > > > > > +    public static class Builder<B extends Builder<B>>
> extends
> > > > > > > > AbstractAppender.Builder<B>
> > > > > > > > +            implements org.apache.logging.log4j.core.
> > > > > > > util.Builder<HttpAppender>
> > > > > > > > {
> > > > > > > > +
> > > > > > > > +        @PluginBuilderAttribute
> > > > > > > > +        @Required(message = "No URL provided for
> > HttpAppender")
> > > > > > > > +        private String url;
> > > > > > > > +
> > > > > > > > +        @PluginBuilderAttribute
> > > > > > > > +        private String method = "POST";
> > > > > > > > +
> > > > > > > > +        @PluginBuilderAttribute
> > > > > > > > +        private int connectTimeoutMillis = 0;
> > > > > > > > +
> > > > > > > > +        @PluginBuilderAttribute
> > > > > > > > +        private int readTimeoutMillis = 0;
> > > > > > > > +
> > > > > > > > +        @PluginElement("Headers")
> > > > > > > > +        private Property[] headers;
> > > > > > > > +
> > > > > > > > +        @Override
> > > > > > > > +        public HttpAppender build() {
> > > > > > > > +            final HttpManager httpManager = new
> > > > > > > > HttpManager(getConfiguration(), getConfiguration().
> > > > > getLoggerContext(),
> > > > > > > > +                getName(), url, method,
> connectTimeoutMillis,
> > > > > > > > readTimeoutMillis, headers);
> > > > > > > > +            return new HttpAppender(getName(), getLayout(),
> > > > > > getFilter(),
> > > > > > > > isIgnoreExceptions(), httpManager);
> > > > > > > > +        }
> > > > > > > > +
> > > > > > > > +        public String getUrl() {
> > > > > > > > +            return url;
> > > > > > > > +        }
> > > > > > > > +
> > > > > > > > +        public String getMethod() {
> > > > > > > > +            return method;
> > > > > > > > +        }
> > > > > > > > +
> > > > > > > > +        public int getConnectTimeoutMillis() {
> > > > > > > > +            return connectTimeoutMillis;
> > > > > > > > +        }
> > > > > > > > +
> > > > > > > > +        public int getReadTimeoutMillis() {
> > > > > > > > +            return readTimeoutMillis;
> > > > > > > > +        }
> > > > > > > > +
> > > > > > > > +        public Property[] getHeaders() {
> > > > > > > > +            return headers;
> > > > > > > > +        }
> > > > > > > > +
> > > > > > > > +        public B setUrl(final String url) {
> > > > > > > > +            this.url = url;
> > > > > > > > +            return asBuilder();
> > > > > > > > +        }
> > > > > > > > +
> > > > > > > > +        public B setMethod(final String method) {
> > > > > > > > +            this.method = method;
> > > > > > > > +            return asBuilder();
> > > > > > > > +        }
> > > > > > > > +
> > > > > > > > +        public B setConnectTimeoutMillis(int
> > > > connectTimeoutMillis) {
> > > > > > > > +            this.connectTimeoutMillis =
> connectTimeoutMillis;
> > > > > > > > +            return asBuilder();
> > > > > > > > +        }
> > > > > > > > +
> > > > > > > > +        public B setReadTimeoutMillis(int
> readTimeoutMillis) {
> > > > > > > > +            this.readTimeoutMillis = readTimeoutMillis;
> > > > > > > > +            return asBuilder();
> > > > > > > > +        }
> > > > > > > > +
> > > > > > > > +        public B setHeaders(final Property[] headers) {
> > > > > > > > +            this.headers = headers;
> > > > > > > > +            return asBuilder();
> > > > > > > > +        }
> > > > > > > > +    }
> > > > > > > > +
> > > > > > > > +    /**
> > > > > > > > +     * @return a builder for a HttpAppender.
> > > > > > > > +     */
> > > > > > > > +    @PluginBuilderFactory
> > > > > > > > +    public static <B extends Builder<B>> B newBuilder() {
> > > > > > > > +        return new Builder<B>().asBuilder();
> > > > > > > > +    }
> > > > > > > > +
> > > > > > > > +    private final HttpManager manager;
> > > > > > > > +
> > > > > > > > +    private HttpAppender(final String name, final Layout<?
> > > extends
> > > > > > > > Serializable> layout, final Filter filter,
> > > > > > > > +                         final boolean ignoreExceptions,
> final
> > > > > > > > HttpManager manager) {
> > > > > > > > +        super(name, filter, layout, ignoreExceptions);
> > > > > > > > +        Objects.requireNonNull(layout, "layout");
> > > > > > > > +        this.manager = Objects.requireNonNull(manager,
> > > > "manager");
> > > > > > > > +    }
> > > > > > > > +
> > > > > > > > +    @Override
> > > > > > > > +    public void append(final LogEvent event) {
> > > > > > > > +        try {
> > > > > > > > +            manager.send(getLayout(), event);
> > > > > > > > +        } catch (final Exception e) {
> > > > > > > > +            error("Unable to send HTTP in appender [" +
> > > getName()
> > > > +
> > > > > > "]",
> > > > > > > > event, e);
> > > > > > > > +        }
> > > > > > > > +    }
> > > > > > > > +
> > > > > > > > +    @Override
> > > > > > > > +    public boolean stop(final long timeout, final TimeUnit
> > > > > timeUnit) {
> > > > > > > > +        setStopping();
> > > > > > > > +        boolean stopped = super.stop(timeout, timeUnit,
> > false);
> > > > > > > > +        stopped &= manager.stop(timeout, timeUnit);
> > > > > > > > +        setStopped();
> > > > > > > > +        return stopped;
> > > > > > > > +    }
> > > > > > > > +
> > > > > > > > +    @Override
> > > > > > > > +    public String toString() {
> > > > > > > > +        return "HttpAppender{" +
> > > > > > > > +            "name=" + getName() +
> > > > > > > > +            ", state=" + getState() +
> > > > > > > > +            '}';
> > > > > > > > +    }
> > > > > > > > +}
> > > > > > > >
> > > > > > > > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/
> > > > > > > > 410f9d36/log4j-core/src/main/java/org/apache/logging/log4j/
> > > > > > > > core/appender/HttpManager.java
> > > > > > > > ------------------------------------------------------------
> > > > > ----------
> > > > > > > > diff --git a/log4j-core/src/main/java/
> > > > org/apache/logging/log4j/core/
> > > > > > > appender/HttpManager.java
> > > > > > > > b/log4j-core/src/main/java/org/apache/logging/log4j/core/
> > > > > > > > appender/HttpManager.java
> > > > > > > > new file mode 100644
> > > > > > > > index 0000000..8f69659
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/log4j-core/src/main/java/
> org/apache/logging/log4j/core/
> > > > > > > > appender/HttpManager.java
> > > > > > > > @@ -0,0 +1,82 @@
> > > > > > > > +/*
> > > > > > > > + * 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.
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +package org.apache.logging.log4j.core.appender;
> > > > > > > > +
> > > > > > > > +import java.io.IOException;
> > > > > > > > +import java.io.OutputStream;
> > > > > > > > +import java.net.HttpURLConnection;
> > > > > > > > +import java.net.MalformedURLException;
> > > > > > > > +import java.net.URL;
> > > > > > > > +import java.util.Objects;
> > > > > > > > +
> > > > > > > > +import org.apache.logging.log4j.core.Layout;
> > > > > > > > +import org.apache.logging.log4j.core.LogEvent;
> > > > > > > > +import org.apache.logging.log4j.core.LoggerContext;
> > > > > > > > +import org.apache.logging.log4j.core.config.Configuration;
> > > > > > > > +import org.apache.logging.log4j.core.
> > > > config.ConfigurationException;
> > > > > > > > +import org.apache.logging.log4j.core.config.Property;
> > > > > > > > +
> > > > > > > > +public class HttpManager extends AbstractManager {
> > > > > > > > +
> > > > > > > > +    private final Configuration configuration;
> > > > > > > > +    private final URL url;
> > > > > > > > +    private final String method;
> > > > > > > > +    private final int connectTimeoutMillis;
> > > > > > > > +    private final int readTimeoutMillis;
> > > > > > > > +    private final Property[] headers;
> > > > > > > > +
> > > > > > > > +    public HttpManager(final Configuration configuration,
> > > > > > LoggerContext
> > > > > > > > loggerContext, final String name,
> > > > > > > > +                       final String url, final String
> method,
> > > > final
> > > > > > int
> > > > > > > > connectTimeoutMillis, final int readTimeoutMillis,
> > > > > > > > +                       final Property[] headers) {
> > > > > > > > +        super(loggerContext, name);
> > > > > > > > +        this.configuration = Objects.requireNonNull(
> > > > configuration);
> > > > > > > > +        try {
> > > > > > > > +            this.url = new URL(url);
> > > > > > > > +        } catch (MalformedURLException e) {
> > > > > > > > +            throw new ConfigurationException(e);
> > > > > > > > +        }
> > > > > > > > +        this.method = Objects.requireNonNull(method,
> > "method");
> > > > > > > > +        this.connectTimeoutMillis = connectTimeoutMillis;
> > > > > > > > +        this.readTimeoutMillis = readTimeoutMillis;
> > > > > > > > +        this.headers = headers != null ? headers : new
> > > > Property[0];
> > > > > > > > +    }
> > > > > > > > +
> > > > > > > > +    public void send(final Layout<?> layout, final LogEvent
> > > event)
> > > > > > > throws
> > > > > > > > IOException {
> > > > > > > > +        HttpURLConnection urlConnection =
> > > (HttpURLConnection)url.
> > > > > > > > openConnection();
> > > > > > > > +        urlConnection.setAllowUserInteraction(false);
> > > > > > > > +        urlConnection.setDoOutput(true);
> > > > > > > > +        urlConnection.setDoInput(true);
> > > > > > > > +        urlConnection.setRequestMethod(method);
> > > > > > > > +        if (connectTimeoutMillis > 0) urlConnection.
> > > > > > setConnectTimeout(
> > > > > > > > connectTimeoutMillis);
> > > > > > > > +        if (readTimeoutMillis > 0)
> > urlConnection.setReadTimeout(
> > > > > > > > readTimeoutMillis);
> > > > > > > > +        if (layout.getContentType() != null) urlConnection.
> > > > > > > > setRequestProperty("Content-Type", layout.getContentType());
> > > > > > > > +        for (Property header : headers) {
> > > > > > > > +            urlConnection.setRequestProperty(
> > > > > > > > +                header.getName(),
> > > > > > > > +                header.isValueNeedsLookup() ? configuration.
> > > > > > > > getStrSubstitutor().replace(event, header.getValue()) :
> > > > > > > > header.getValue());
> > > > > > > > +        }
> > > > > > > > +        byte[] msg = layout.toByteArray(event);
> > > > > > > > +        urlConnection.setFixedLengthStreamingMode(
> > msg.length);
> > > > > > > > +        urlConnection.connect();
> > > > > > > > +        try (OutputStream os =
> urlConnection.getOutputStream(
> > ))
> > > {
> > > > > > > > +            os.write(msg);
> > > > > > > > +        }
> > > > > > > > +        urlConnection.getInputStream().close();
> > > > > > > > +    }
> > > > > > > > +
> > > > > > > > +}
> > > > > > > >
> > > > > > > > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/
> > > > > > > > 410f9d36/log4j-core/src/test/java/org/apache/logging/log4j/
> > > > > > > core/appender/
> > > > > > > > HttpAppenderTest.java
> > > > > > > > ------------------------------------------------------------
> > > > > ----------
> > > > > > > > diff --git a/log4j-core/src/test/java/
> > > > org/apache/logging/log4j/core/
> > > > > > > appender/HttpAppenderTest.java
> > > > > > > > b/log4j-core/src/test/java/org/apache/logging/log4j/core/
> > > > > > > > appender/HttpAppenderTest.java
> > > > > > > > new file mode 100644
> > > > > > > > index 0000000..98120a1
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/log4j-core/src/test/java/
> org/apache/logging/log4j/core/
> > > > > > > > appender/HttpAppenderTest.java
> > > > > > > > @@ -0,0 +1,52 @@
> > > > > > > > +package org.apache.logging.log4j.core.appender;
> > > > > > > > +
> > > > > > > > +import org.apache.logging.log4j.Level;
> > > > > > > > +import org.apache.logging.log4j.core.Appender;
> > > > > > > > +import org.apache.logging.log4j.core.impl.Log4jLogEvent;
> > > > > > > > +import org.apache.logging.log4j.junit.LoggerContextRule;
> > > > > > > > +import org.apache.logging.log4j.message.SimpleMessage;
> > > > > > > > +import org.junit.Rule;
> > > > > > > > +import org.junit.Test;
> > > > > > > > +
> > > > > > > > +// TODO this test requires manual verification
> > > > > > > > +public class HttpAppenderTest {
> > > > > > > > +
> > > > > > > > +    private static final String LOG_MESSAGE = "Hello,
> world!";
> > > > > > > > +
> > > > > > > > +    private static Log4jLogEvent createLogEvent() {
> > > > > > > > +        return Log4jLogEvent.newBuilder()
> > > > > > > > +            .setLoggerName(HttpAppenderTest.class.
> getName())
> > > > > > > > +            .setLoggerFqcn(HttpAppenderTest.class.
> getName())
> > > > > > > > +            .setLevel(Level.INFO)
> > > > > > > > +            .setMessage(new SimpleMessage(LOG_MESSAGE))
> > > > > > > > +            .build();
> > > > > > > > +    }
> > > > > > > > +
> > > > > > > > +    @Rule
> > > > > > > > +    public LoggerContextRule ctx = new LoggerContextRule("
> > > > > > > > HttpAppenderTest.xml");
> > > > > > > > +
> > > > > > > > +    @Test
> > > > > > > > +    public void testAppendSuccess() throws Exception {
> > > > > > > > +        final Appender appender = ctx.getRequiredAppender("
> > > > > > > HttpSuccess");
> > > > > > > > +        appender.append(createLogEvent());
> > > > > > > > +    }
> > > > > > > > +
> > > > > > > > +    @Test
> > > > > > > > +    public void testAppendErrorIgnore() throws Exception {
> > > > > > > > +        final Appender appender = ctx.getRequiredAppender("
> > > > > > > > HttpErrorIgnore");
> > > > > > > > +        appender.append(createLogEvent());
> > > > > > > > +    }
> > > > > > > > +
> > > > > > > > +    @Test(expected = AppenderLoggingException.class)
> > > > > > > > +    public void testAppendError() throws Exception {
> > > > > > > > +        final Appender appender = ctx.getRequiredAppender("
> > > > > > HttpError");
> > > > > > > > +        appender.append(createLogEvent());
> > > > > > > > +    }
> > > > > > > > +
> > > > > > > > +    @Test
> > > > > > > > +    public void testAppendSubst() throws Exception {
> > > > > > > > +        final Appender appender = ctx.getRequiredAppender("
> > > > > > HttpSubst");
> > > > > > > > +        appender.append(createLogEvent());
> > > > > > > > +    }
> > > > > > > > +
> > > > > > > > +}
> > > > > > > > \ No newline at end of file
> > > > > > > >
> > > > > > > > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/
> > > > > > > > 410f9d36/log4j-core/src/test/resources/HttpAppenderTest.xml
> > > > > > > > ------------------------------------------------------------
> > > > > ----------
> > > > > > > > diff --git a/log4j-core/src/test/
> > resources/HttpAppenderTest.xml
> > > > > > > > b/log4j-core/src/test/resources/HttpAppenderTest.xml
> > > > > > > > new file mode 100644
> > > > > > > > index 0000000..30edaa0
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/log4j-core/src/test/resources/HttpAppenderTest.xml
> > > > > > > > @@ -0,0 +1,43 @@
> > > > > > > > +<?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.
> > > > > > > > +  -->
> > > > > > > > +<Configuration name="HttpAppenderTest" status="WARN">
> > > > > > > > +  <Appenders>
> > > > > > > > +    <Http name="HttpSuccess" url="http://localhost:9200/
> > > > test/log4j/
> > > > > ">
> > > > > > > > +      <Property name="X-Test" value="header value" />
> > > > > > > > +      <JsonLayout properties="true"/>
> > > > > > > > +    </Http>
> > > > > > > > +    <Http name="HttpErrorIgnore" url="
> http://localhost:9200/
> > > > > > test/log4j/
> > > > > > > "
> > > > > > > > method="PUT">
> > > > > > > > +      <JsonLayout properties="true"/>
> > > > > > > > +    </Http>
> > > > > > > > +    <Http name="HttpError" url="http://localhost:9200/
> > > test/log4j/
> > > > "
> > > > > > > > method="PUT" ignoreExceptions="false">
> > > > > > > > +      <JsonLayout properties="true"/>
> > > > > > > > +    </Http>
> > > > > > > > +    <Http name="HttpSubst" url="http://localhost:9200/
> > > test/log4j/
> > > > ">
> > > > > > > > +      <Property name="X-Test" value="$${java:runtime}" />
> > > > > > > > +      <JsonLayout properties="true"/>
> > > > > > > > +    </Http>
> > > > > > > > +  </Appenders>
> > > > > > > > +  <Loggers>
> > > > > > > > +    <Root level="info">
> > > > > > > > +      <AppenderRef ref="HttpSuccess"/>
> > > > > > > > +      <AppenderRef ref="HttpErrorIgnore"/>
> > > > > > > > +      <AppenderRef ref="HttpError"/>
> > > > > > > > +      <AppenderRef ref="HttpSubst"/>
> > > > > > > > +    </Root>
> > > > > > > > +  </Loggers>
> > > > > > > > +</Configuration>
> > > > > > > > \ No newline at end of file
> > > > > > > >
> > > > > > > > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/
> > > > > > > > 410f9d36/src/changes/changes.xml
> > > > > > > > ------------------------------------------------------------
> > > > > ----------
> > > > > > > > diff --git a/src/changes/changes.xml
> b/src/changes/changes.xml
> > > > > > > > index 379c21e..d0f8133 100644
> > > > > > > > --- a/src/changes/changes.xml
> > > > > > > > +++ b/src/changes/changes.xml
> > > > > > > > @@ -31,6 +31,9 @@
> > > > > > > >           - "remove" - Removed
> > > > > > > >      -->
> > > > > > > >      <release version="2.9.0" date="2017-MM-DD"
> description="GA
> > > > > Release
> > > > > > > > 2.9.0">
> > > > > > > > +      <action issue="LOG4J2-1442" dev="mikes" type="add">
> > > > > > > > +        Generic HTTP appender.
> > > > > > > > +      </action>
> > > > > > > >        <action issue="LOG4J2-1854" dev="mikes" type="add"
> > > > > > due-to="Xavier
> > > > > > > > Jodoin">
> > > > > > > >          Support null byte delimiter in GelfLayout.
> > > > > > > >        </action>
> > > > > > > >
> > > > > > > > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/
> > > > > > > > 410f9d36/src/site/site.xml
> > > > > > > > ------------------------------------------------------------
> > > > > ----------
> > > > > > > > diff --git a/src/site/site.xml b/src/site/site.xml
> > > > > > > > index e380c82..aa161fe 100644
> > > > > > > > --- a/src/site/site.xml
> > > > > > > > +++ b/src/site/site.xml
> > > > > > > > @@ -134,6 +134,7 @@
> > > > > > > >          <item name="JDBC" href="/manual/appenders.html#
> > > > > > JDBCAppender"/>
> > > > > > > >          <item name="JMS" href="/manual/appenders.html#
> > > > > JMSAppender"/>
> > > > > > > >          <item name="JPA" href="/manual/appenders.html#
> > > > > JPAAppender"/>
> > > > > > > > +        <item name="HTTP" href="/manual/appenders.html#
> > > > > > HttpAppender"/>
> > > > > > > >          <item name="Kafka" href="/manual/appenders.html#
> > > > > > > KafkaAppender"/>
> > > > > > > >          <item name="Memory Mapped File"
> > > > > href="/manual/appenders.html#
> > > > > > > > MemoryMappedFileAppender"/>
> > > > > > > >          <item name="NoSQL" href="/manual/appenders.html#
> > > > > > > NoSQLAppender"/>
> > > > > > > >
> > > > > > > > http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/
> > > > > > > > 410f9d36/src/site/xdoc/manual/appenders.xml
> > > > > > > > ------------------------------------------------------------
> > > > > ----------
> > > > > > > > diff --git a/src/site/xdoc/manual/appenders.xml
> > > > > > b/src/site/xdoc/manual/
> > > > > > > > appenders.xml
> > > > > > > > index 28d9aa4..f7721df 100644
> > > > > > > > --- a/src/site/xdoc/manual/appenders.xml
> > > > > > > > +++ b/src/site/xdoc/manual/appenders.xml
> > > > > > > > @@ -1538,6 +1538,84 @@ public class JpaLogEntity extends
> > > > > > > > AbstractLogEventWrapperEntity {
> > > > > > > >      ...
> > > > > > > >  }]]></pre>
> > > > > > > >          </subsection>
> > > > > > > > +        <a name="HttpAppender"/>
> > > > > > > > +        <subsection name="HttpAppender">
> > > > > > > > +          <p>
> > > > > > > > +            The HttpAppender sends log events over HTTP. A
> > > Layout
> > > > > must
> > > > > > > be
> > > > > > > > provided to format the LogEvent.
> > > > > > > > +          </p>
> > > > > > > > +          <p>
> > > > > > > > +            Will set the <code>Content-Type</code> header
> > > > according
> > > > > to
> > > > > > > > the layout. Additional headers can be specified
> > > > > > > > +            with embedded Property elements.
> > > > > > > > +          </p>
> > > > > > > > +          <table>
> > > > > > > > +            <caption align="top">HttpAppender
> > > Parameters</caption>
> > > > > > > > +            <tr>
> > > > > > > > +              <th>Parameter Name</th>
> > > > > > > > +              <th>Type</th>
> > > > > > > > +              <th>Description</th>
> > > > > > > > +            </tr>
> > > > > > > > +            <tr>
> > > > > > > > +              <td>name</td>
> > > > > > > > +              <td>String</td>
> > > > > > > > +              <td>The name of the Appender.</td>
> > > > > > > > +            </tr>
> > > > > > > > +            <tr>
> > > > > > > > +              <td>filter</td>
> > > > > > > > +              <td>Filter</td>
> > > > > > > > +              <td>A Filter to determine if the event should
> be
> > > > > handled
> > > > > > > by
> > > > > > > > this Appender. More than one Filter
> > > > > > > > +                may be used by using a CompositeFilter.</td>
> > > > > > > > +            </tr>
> > > > > > > > +            <tr>
> > > > > > > > +              <td>layout</td>
> > > > > > > > +              <td>Layout</td>
> > > > > > > > +              <td>The Layout to use to format the
> > LogEvent.</td>
> > > > > > > > +            </tr>
> > > > > > > > +            <tr>
> > > > > > > > +              <td>url</td>
> > > > > > > > +              <td>string</td>
> > > > > > > > +              <td>The URL to use. The URL scheme must be
> > "http"
> > > or
> > > > > > > > "https".</td>
> > > > > > > > +            </tr>
> > > > > > > > +            <tr>
> > > > > > > > +              <td>method</td>
> > > > > > > > +              <td>string</td>
> > > > > > > > +              <td>The HTTP method to use. Optional, default
> is
> > > > > > > > "POST".</td>
> > > > > > > > +            </tr>
> > > > > > > > +            <tr>
> > > > > > > > +              <td>connectTimeoutMillis</td>
> > > > > > > > +              <td>integer</td>
> > > > > > > > +              <td>The connect timeout in milliseconds.
> > Optional,
> > > > > > default
> > > > > > > > is 0 (infinite timeout).</td>
> > > > > > > > +            </tr>
> > > > > > > > +            <tr>
> > > > > > > > +              <td>readTimeoutMillis</td>
> > > > > > > > +              <td>integer</td>
> > > > > > > > +              <td>The socket read timeout in milliseconds.
> > > > Optional,
> > > > > > > > default is 0 (infinite timeout).</td>
> > > > > > > > +            </tr>
> > > > > > > > +            <tr>
> > > > > > > > +              <td>headers</td>
> > > > > > > > +              <td>Property[]</td>
> > > > > > > > +              <td>Additional HTTP headers to use. The values
> > > > support
> > > > > > <a
> > > > > > > > href="lookups.html">lookups</a></td>
> > > > > > > > +            </tr>
> > > > > > > > +            <tr>
> > > > > > > > +              <td>ignoreExceptions</td>
> > > > > > > > +              <td>boolean</td>
> > > > > > > > +              <td>The default is <code>true</code>, causing
> > > > > exceptions
> > > > > > > > encountered while appending events to be
> > > > > > > > +                internally logged and then ignored. When set
> > to
> > > > > > > > <code>false</code> exceptions will be propagated to the
> > > > > > > > +                caller, instead. You must set this to
> > > > > > <code>false</code>
> > > > > > > > when wrapping this Appender in a
> > > > > > > > +                <a href="#FailoverAppender">
> > > > > > FailoverAppender</a>.</td>
> > > > > > > > +            </tr>
> > > > > > > > +          </table>
> > > > > > > > +          <p>
> > > > > > > > +            Here is a sample HttpAppender configuration
> > snippet:
> > > > > > > > +          </p>
> > > > > > > > +          <pre class="prettyprint linenums"><![CDATA[<?xml
> > > > > > version="1.0"
> > > > > > > > encoding="UTF-8"?>
> > > > > > > > +  ...
> > > > > > > > +  <Appenders>
> > > > > > > > +    <Http name="Http" url="http://localhost:9200/
> test/log4j/
> > ">
> > > > > > > > +      <Property name="X-Java-Runtime"
> value="$${java:runtime}"
> > > />
> > > > > > > > +      <JsonLayout properties="true"/>
> > > > > > > > +    </Http>
> > > > > > > > +  </Appenders>]]></pre>
> > > > > > > > +        </subsection>
> > > > > > > >          <a name="KafkaAppender"/>
> > > > > > > >          <subsection name="KafkaAppender">
> > > > > > > >            <p>
> > > > > > > >
> > > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > --
> > > > > > > Matt Sicker <boa...@gmail.com>
> > > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > > --
> > > > > > [image: MagineTV]
> > > > > >
> > > > > > *Mikael Ståldal*
> > > > > > Senior software developer
> > > > > >
> > > > > > *Magine TV*
> > > > > > mikael.stal...@magine.com
> > > > > > Grev Turegatan 3  | 114 46 Stockholm, Sweden  |   www.magine.com
> > > > > >
> > > > > > Privileged and/or Confidential Information may be contained in
> this
> > > > > > message. If you are not the addressee indicated in this message
> > > > > > (or responsible for delivery of the message to such a person),
> you
> > > may
> > > > > not
> > > > > > copy or deliver this message to anyone. In such case,
> > > > > > you should destroy this message and kindly notify the sender by
> > reply
> > > > > > email.
> > > > > >
> > > > >
> > > > >
> > > > >
> > > > > --
> > > > > Matt Sicker <boa...@gmail.com>
> > > > >
> > > >
> > > >
> > > >
> > > > --
> > > > [image: MagineTV]
> > > >
> > > > *Mikael Ståldal*
> > > > Senior software developer
> > > >
> > > > *Magine TV*
> > > > mikael.stal...@magine.com
> > > > Grev Turegatan 3  | 114 46 Stockholm, Sweden  |   www.magine.com
> > > >
> > > > Privileged and/or Confidential Information may be contained in this
> > > > message. If you are not the addressee indicated in this message
> > > > (or responsible for delivery of the message to such a person), you
> may
> > > not
> > > > copy or deliver this message to anyone. In such case,
> > > > you should destroy this message and kindly notify the sender by reply
> > > > email.
> > > >
> > >
> > >
> > >
> > > --
> > > Matt Sicker <boa...@gmail.com>
> > >
> >
> >
> >
> > --
> > [image: MagineTV]
> >
> > *Mikael Ståldal*
> > Senior software developer
> >
> > *Magine TV*
> > mikael.stal...@magine.com
> > Grev Turegatan 3  | 114 46 Stockholm, Sweden  |   www.magine.com
> >
> > Privileged and/or Confidential Information may be contained in this
> > message. If you are not the addressee indicated in this message
> > (or responsible for delivery of the message to such a person), you may
> not
> > copy or deliver this message to anyone. In such case,
> > you should destroy this message and kindly notify the sender by reply
> > email.
> >
>
>
>
> --
> Matt Sicker <boa...@gmail.com>
>



-- 
[image: MagineTV]

*Mikael Ståldal*
Senior software developer

*Magine TV*
mikael.stal...@magine.com
Grev Turegatan 3  | 114 46 Stockholm, Sweden  |   www.magine.com

Privileged and/or Confidential Information may be contained in this
message. If you are not the addressee indicated in this message
(or responsible for delivery of the message to such a person), you may not
copy or deliver this message to anyone. In such case,
you should destroy this message and kindly notify the sender by reply
email.

Reply via email to