View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  
18  package org.apache.logging.log4j.core.appender;
19  
20  import java.io.Serializable;
21  import java.net.URL;
22  import java.util.Objects;
23  import java.util.concurrent.TimeUnit;
24  
25  import org.apache.logging.log4j.core.Appender;
26  import org.apache.logging.log4j.core.Filter;
27  import org.apache.logging.log4j.core.Layout;
28  import org.apache.logging.log4j.core.LogEvent;
29  import org.apache.logging.log4j.core.config.Node;
30  import org.apache.logging.log4j.core.config.Property;
31  import org.apache.logging.log4j.core.config.plugins.Plugin;
32  import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
33  import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
34  import org.apache.logging.log4j.core.config.plugins.PluginElement;
35  import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
36  import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
37  
38  /**
39   * Sends log events over HTTP.
40   */
41  @Plugin(name = "Http", category = Node.CATEGORY, elementType = Appender.ELEMENT_TYPE, printObject = true)
42  public final class HttpAppender extends AbstractAppender {
43  
44      /**
45       * Builds HttpAppender instances.
46       * @param <B> The type to build
47       */
48      public static class Builder<B extends Builder<B>> extends AbstractAppender.Builder<B>
49              implements org.apache.logging.log4j.core.util.Builder<HttpAppender> {
50  
51          @PluginBuilderAttribute
52          @Required(message = "No URL provided for HttpAppender")
53          private URL url;
54  
55          @PluginBuilderAttribute
56          private String method = "POST";
57  
58          @PluginBuilderAttribute
59          private int connectTimeoutMillis = 0;
60  
61          @PluginBuilderAttribute
62          private int readTimeoutMillis = 0;
63  
64          @PluginElement("Headers")
65          private Property[] headers;
66  
67          @PluginElement("SslConfiguration")
68          private SslConfiguration sslConfiguration;
69  
70          @PluginBuilderAttribute
71          private boolean verifyHostname = true;
72  
73          @Override
74          public HttpAppender build() {
75              final HttpManager httpManager = new HttpURLConnectionManager(getConfiguration(), getConfiguration().getLoggerContext(),
76                  getName(), url, method, connectTimeoutMillis, readTimeoutMillis, headers, sslConfiguration, verifyHostname);
77              return new HttpAppender(getName(), getLayout(), getFilter(), isIgnoreExceptions(), httpManager);
78          }
79  
80          public URL getUrl() {
81              return url;
82          }
83  
84          public String getMethod() {
85              return method;
86          }
87  
88          public int getConnectTimeoutMillis() {
89              return connectTimeoutMillis;
90          }
91  
92          public int getReadTimeoutMillis() {
93              return readTimeoutMillis;
94          }
95  
96          public Property[] getHeaders() {
97              return headers;
98          }
99  
100         public SslConfiguration getSslConfiguration() {
101             return sslConfiguration;
102         }
103 
104         public boolean isVerifyHostname() {
105             return verifyHostname;
106         }
107 
108         public B setUrl(final URL url) {
109             this.url = url;
110             return asBuilder();
111         }
112 
113         public B setMethod(final String method) {
114             this.method = method;
115             return asBuilder();
116         }
117 
118         public B setConnectTimeoutMillis(final int connectTimeoutMillis) {
119             this.connectTimeoutMillis = connectTimeoutMillis;
120             return asBuilder();
121         }
122 
123         public B setReadTimeoutMillis(final int readTimeoutMillis) {
124             this.readTimeoutMillis = readTimeoutMillis;
125             return asBuilder();
126         }
127 
128         public B setHeaders(final Property[] headers) {
129             this.headers = headers;
130             return asBuilder();
131         }
132 
133         public B setSslConfiguration(final SslConfiguration sslConfiguration) {
134             this.sslConfiguration = sslConfiguration;
135             return asBuilder();
136         }
137 
138         public B setVerifyHostname(final boolean verifyHostname) {
139             this.verifyHostname = verifyHostname;
140             return asBuilder();
141         }
142     }
143 
144     /**
145      * @return a builder for a HttpAppender.
146      */
147     @PluginBuilderFactory
148     public static <B extends Builder<B>> B newBuilder() {
149         return new Builder<B>().asBuilder();
150     }
151 
152     private final HttpManager manager;
153 
154     private HttpAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
155                          final boolean ignoreExceptions, final HttpManager manager) {
156         super(name, filter, layout, ignoreExceptions);
157         Objects.requireNonNull(layout, "layout");
158         this.manager = Objects.requireNonNull(manager, "manager");
159     }
160 
161     @Override
162     public void start() {
163         super.start();
164         manager.startup();
165     }
166 
167     @Override
168     public void append(final LogEvent event) {
169         try {
170             manager.send(getLayout(), event);
171         } catch (final Exception e) {
172             error("Unable to send HTTP in appender [" + getName() + "]", event, e);
173         }
174     }
175 
176     @Override
177     public boolean stop(final long timeout, final TimeUnit timeUnit) {
178         setStopping();
179         boolean stopped = super.stop(timeout, timeUnit, false);
180         stopped &= manager.stop(timeout, timeUnit);
181         setStopped();
182         return stopped;
183     }
184 
185     @Override
186     public String toString() {
187         return "HttpAppender{" +
188             "name=" + getName() +
189             ", state=" + getState() +
190             '}';
191     }
192 }