├── .travis.yml ├── .idea ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── modules.xml ├── misc.xml └── compiler.xml ├── src ├── test │ └── java │ │ └── tw │ │ └── kewang │ │ └── logback │ │ └── appender │ │ └── AppTest.java └── main │ ├── java │ └── tw │ │ └── kewang │ │ └── logback │ │ └── appender │ │ ├── Authentication.java │ │ ├── HttpAuthenticationAppender.java │ │ ├── HttpAppender.java │ │ └── HttpAppenderAbstract.java │ └── resources │ └── logback.xml ├── LICENSE ├── README.md ├── pom.xml ├── .gitignore └── logback-http-appender.iml /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/test/java/tw/kewang/logback/appender/AppTest.java: -------------------------------------------------------------------------------- 1 | package tw.kewang.logback.appender; 2 | 3 | import org.junit.Test; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | public class AppTest { 8 | private static final Logger LOG = LoggerFactory.getLogger(AppTest.class); 9 | 10 | @Test 11 | public void testApp() { 12 | try { 13 | throw new RuntimeException("Oops"); 14 | } catch (Exception e) { 15 | LOG.error("Caught Exception: ", e); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/tw/kewang/logback/appender/Authentication.java: -------------------------------------------------------------------------------- 1 | package tw.kewang.logback.appender; 2 | 3 | public class Authentication { 4 | 5 | private String username; 6 | private String password; 7 | 8 | public String getUsername() { 9 | return username; 10 | } 11 | 12 | public String getPassword() { 13 | return password; 14 | } 15 | 16 | public void setUsername(String username) { 17 | this.username = username; 18 | } 19 | 20 | public void setPassword(String password) { 21 | this.password = password; 22 | } 23 | 24 | public boolean isConfigured() { 25 | return HttpAppenderAbstract.isStringEmptyOrNull(username) == false && HttpAppenderAbstract.isStringEmptyOrNull(password) == false; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Kewang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Redmine-Appender 4 | 5 | 6 | 7 | 8 | 9 | 10 | ${PATTERN} 11 | ${CHARSET} 12 | 13 | 14 | 15 | 16 | ${LOG_HOME}/myLog.log 17 | 18 | ${PATTERN} 19 | ${CHARSET} 20 | 21 | 22 | 23 | 24 | post 25 | http://example.com/issues.json 26 | json 27 | {"issue": {"subject": "$subject", "project_id": 22, "description": "$event"}} 28 | {"X-Redmine-API-Key": "hello-this-is-a-key", "Another": "also-key"} 29 | 30 | ${PATTERN} 31 | ${CHARSET} 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # logback-http-appender 2 | 3 | [![Build Status](https://travis-ci.org/kewang/logback-http-appender.svg?branch=master)](https://travis-ci.org/kewang/logback-http-appender) 4 | 5 | ## How to use 6 | 7 | ```xml 8 | 9 | https 10 | localhost 11 | 443 12 | /logs/logstash 13 | 14 | username 15 | senha 16 | 17 | 10 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | { 29 | "appName": "upp-quality-control-framework-ws" 30 | } 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | ``` 46 | 47 | ## References 48 | 49 | * [Chapter 4: Appenders](http://logback.qos.ch/manual/appenders.html) 50 | * [logback-redis-appender](https://github.com/kmtong/logback-redis-appender) 51 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | tw.kewang 6 | logback-http-appender 7 | 0.2.0-SNAPSHOT 8 | jar 9 | 10 | logback-http-appender 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | junit 20 | junit 21 | 4.12 22 | test 23 | 24 | 25 | ch.qos.logback 26 | logback-classic 27 | 1.2.1 28 | 29 | 30 | commons-io 31 | commons-io 32 | 2.5 33 | 34 | 35 | org.json 36 | json 37 | 20160212 38 | 39 | 40 | 41 | 42 | 43 | 44 | org.apache.maven.plugins 45 | maven-compiler-plugin 46 | 3.6.1 47 | 48 | 1.8 49 | 1.8 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/maven,intellij,java 2 | 3 | ### Maven ### 4 | target/ 5 | pom.xml.tag 6 | pom.xml.releaseBackup 7 | pom.xml.versionsBackup 8 | pom.xml.next 9 | release.properties 10 | dependency-reduced-pom.xml 11 | buildNumber.properties 12 | .mvn/timing.properties 13 | 14 | 15 | ### Intellij ### 16 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 17 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 18 | 19 | # User-specific stuff: 20 | .idea/workspace.xml 21 | .idea/tasks.xml 22 | .idea/dictionaries 23 | .idea/vcs.xml 24 | .idea/jsLibraryMappings.xml 25 | 26 | # Sensitive or high-churn files: 27 | .idea/dataSources.ids 28 | .idea/dataSources.xml 29 | .idea/dataSources.local.xml 30 | .idea/sqlDataSources.xml 31 | .idea/dynamic.xml 32 | .idea/uiDesigner.xml 33 | 34 | # Gradle: 35 | .idea/gradle.xml 36 | .idea/libraries 37 | 38 | # Mongo Explorer plugin: 39 | .idea/mongoSettings.xml 40 | 41 | ## File-based project format: 42 | *.iws 43 | 44 | ## Plugin-specific files: 45 | 46 | # IntelliJ 47 | /out/ 48 | 49 | # mpeltonen/sbt-idea plugin 50 | .idea_modules/ 51 | 52 | # JIRA plugin 53 | atlassian-ide-plugin.xml 54 | 55 | # Crashlytics plugin (for Android Studio and IntelliJ) 56 | com_crashlytics_export_strings.xml 57 | crashlytics.properties 58 | crashlytics-build.properties 59 | fabric.properties 60 | 61 | ### Intellij Patch ### 62 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 63 | 64 | # *.iml 65 | # modules.xml 66 | # .idea/misc.xml 67 | # *.ipr 68 | 69 | 70 | ### Java ### 71 | *.class 72 | 73 | # Mobile Tools for Java (J2ME) 74 | .mtj.tmp/ 75 | 76 | # Package Files # 77 | *.jar 78 | *.war 79 | *.ear 80 | 81 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 82 | hs_err_pid* 83 | 84 | ### Custom ### 85 | *.log 86 | 87 | .classpath 88 | .project 89 | .settings 90 | -------------------------------------------------------------------------------- /src/main/java/tw/kewang/logback/appender/HttpAuthenticationAppender.java: -------------------------------------------------------------------------------- 1 | package tw.kewang.logback.appender; 2 | 3 | import java.net.HttpURLConnection; 4 | import java.net.URL; 5 | 6 | /** 7 | * Provide basic http authentication. 8 | * 9 | * @author Thiago Diniz da Silveira 10 | * 11 | */ 12 | public class HttpAuthenticationAppender extends HttpAppenderAbstract { 13 | 14 | private static final String SEPARATOR_BASIC_AUTHENTICATION = ":"; 15 | 16 | protected Authentication authentication; 17 | protected String encondedUserPassword; 18 | 19 | @SuppressWarnings("restriction") 20 | @Override 21 | public void start() { 22 | super.start(); 23 | if (authentication == null || authentication.isConfigured() == false) { 24 | addError("No authentication was configured. Use to specify the and the for Basic Authentication."); 25 | return; 26 | } 27 | 28 | String userPassword = authentication.getUsername() + SEPARATOR_BASIC_AUTHENTICATION + authentication.getPassword(); 29 | encondedUserPassword = new sun.misc.BASE64Encoder().encode(userPassword.getBytes()); 30 | 31 | openConnection(); 32 | addInfo("Using Basic Authentication"); 33 | } 34 | 35 | @Override 36 | protected HttpURLConnection openConnection() { 37 | HttpURLConnection conn = null; 38 | try { 39 | URL urlObj = new URL(protocol, url, port, path); 40 | conn = (HttpURLConnection) urlObj.openConnection(); 41 | conn.setRequestProperty("Authorization", "Basic " + encondedUserPassword); 42 | conn.setRequestMethod("POST"); 43 | return conn; 44 | } catch (Exception e) { 45 | addError("Error to open connection Exception: ", e); 46 | return null; 47 | } finally { 48 | try { 49 | if (conn != null) { 50 | conn.disconnect(); 51 | } 52 | } catch (Exception e) { 53 | addError("Error to open connection Exception: ", e); 54 | return null; 55 | } 56 | } 57 | } 58 | 59 | public Authentication getAuthentication() { 60 | return authentication; 61 | } 62 | 63 | public void setAuthentication(Authentication authentication) { 64 | this.authentication = authentication; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/tw/kewang/logback/appender/HttpAppender.java: -------------------------------------------------------------------------------- 1 | package tw.kewang.logback.appender; 2 | 3 | import java.io.IOException; 4 | import java.net.HttpURLConnection; 5 | import java.net.URL; 6 | import java.nio.charset.Charset; 7 | 8 | import org.apache.commons.io.IOUtils; 9 | import org.json.JSONObject; 10 | 11 | import ch.qos.logback.classic.spi.ILoggingEvent; 12 | import ch.qos.logback.core.Layout; 13 | import ch.qos.logback.core.encoder.Encoder; 14 | 15 | public class HttpAppender extends HttpAppenderAbstract { 16 | 17 | /** 18 | * Defines default method to send data. 19 | */ 20 | protected final static String DEFAULT_METHOD = "POST"; 21 | 22 | protected String method = "POST"; 23 | 24 | @Override 25 | public void start() { 26 | normalizeMethodName(); 27 | 28 | super.start(); 29 | } 30 | 31 | protected void checkProperties() { 32 | if (isStringEmptyOrNull(url)) { 33 | url = DEFAULT_URL; 34 | addInfo(String.format(MSG_NOT_SET, "url", url)); 35 | } else { 36 | addInfo(String.format(MSG_USING, "url", url)); 37 | } 38 | 39 | if (isStringEmptyOrNull(method)) { 40 | method = DEFAULT_METHOD; 41 | addInfo(String.format(MSG_NOT_SET, "method", method)); 42 | } else { 43 | addInfo(String.format(MSG_USING, "method", method)); 44 | } 45 | } 46 | 47 | @Override 48 | public void append(ILoggingEvent event) { 49 | createIssue(event); 50 | } 51 | 52 | public void createIssue(ILoggingEvent event) { 53 | HttpURLConnection conn = null; 54 | 55 | try { 56 | URL urlObj = new URL(url); 57 | addInfo("URL: " + url); 58 | conn = (HttpURLConnection) urlObj.openConnection(); 59 | conn.setRequestMethod(method); 60 | transformHeaders(conn); 61 | boolean isOk = false; 62 | byte[] objEncoded = encoder.encode(event); 63 | if (method.equals("GET") || method.equals("DELETE")) { 64 | isOk = sendNoBodyRequest(conn); 65 | } else if (method.equals("POST") || method.equals("PUT")) { 66 | isOk = sendBodyRequest(objEncoded, conn); 67 | } 68 | 69 | if (!isOk) { 70 | addError("Not OK"); 71 | return; 72 | } 73 | } catch (Exception e) { 74 | addError("Exception", e); 75 | return; 76 | } finally { 77 | try { 78 | if (conn != null) { 79 | conn.disconnect(); 80 | } 81 | } catch (Exception e) { 82 | addError("Exception", e); 83 | return; 84 | } 85 | } 86 | } 87 | 88 | private void normalizeMethodName() { 89 | method = method.toUpperCase(); 90 | } 91 | 92 | protected void transformHeaders(HttpURLConnection conn) { 93 | conn.setRequestProperty("Content-Type", contentType); 94 | if (headers == null || headers.isEmpty()) { 95 | return; 96 | } 97 | 98 | JSONObject jObj = new JSONObject(headers); 99 | for (String key : jObj.keySet()) { 100 | String value = (String) jObj.get(key); 101 | conn.setRequestProperty(key, value); 102 | } 103 | 104 | } 105 | 106 | protected boolean sendNoBodyRequest(HttpURLConnection conn) throws IOException { 107 | return showResponse(conn); 108 | } 109 | 110 | protected boolean sendBodyRequest(byte[] objEncoded, HttpURLConnection conn) throws IOException { 111 | conn.setDoOutput(true); 112 | if (body != null) { 113 | addInfo("Body: " + body); 114 | IOUtils.write(body, conn.getOutputStream(), Charset.defaultCharset()); 115 | } else { 116 | IOUtils.write(objEncoded, conn.getOutputStream()); 117 | } 118 | return showResponse(conn); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /logback-http-appender.iml: -------------------------------------------------------------------------------- 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 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /src/main/java/tw/kewang/logback/appender/HttpAppenderAbstract.java: -------------------------------------------------------------------------------- 1 | package tw.kewang.logback.appender; 2 | 3 | import java.io.IOException; 4 | import java.net.HttpURLConnection; 5 | import java.net.URL; 6 | import java.nio.charset.Charset; 7 | import java.time.Duration; 8 | 9 | import org.apache.commons.io.IOUtils; 10 | import org.json.JSONObject; 11 | 12 | import ch.qos.logback.classic.spi.ILoggingEvent; 13 | import ch.qos.logback.core.Layout; 14 | import ch.qos.logback.core.UnsynchronizedAppenderBase; 15 | import ch.qos.logback.core.encoder.Encoder; 16 | 17 | public abstract class HttpAppenderAbstract extends UnsynchronizedAppenderBase { 18 | 19 | /** 20 | * Defines default port to get access. 21 | */ 22 | protected final static int DEFAULT_PORT = 8080; 23 | 24 | /** 25 | * Defines default protocol to use between HTTP or HTTPS. 26 | */ 27 | protected final static String DEFAULT_PROTOCOL = "http"; 28 | 29 | /** 30 | * Defines default content type to send data. 31 | */ 32 | protected final static String DEFAULT_CONTENT_TYPE = "json"; 33 | 34 | /** 35 | * Defines default URL server. 36 | */ 37 | protected final static String DEFAULT_URL = "localhost"; 38 | 39 | /** 40 | * Defines default server path. 41 | */ 42 | protected final static String DEFAULT_PATH = "/"; 43 | 44 | /** 45 | * Defines default time in seconds to try to reconnect if connection is lost. 46 | */ 47 | protected final static int DEFAULT_RECONNECT_DELAY = 30; 48 | 49 | protected final String MSG_USING = "Using %s: %s"; 50 | protected final String MSG_NOT_SET = "Assuming default value for %s: %s"; 51 | 52 | protected Encoder encoder; 53 | protected Layout layout; 54 | protected String url; 55 | 56 | protected String protocol; 57 | protected String path; 58 | protected int port; 59 | protected String contentType; 60 | protected String body; 61 | protected String headers; 62 | protected int reconnectDelay; 63 | 64 | @Override 65 | public void start() { 66 | if (encoder == null) { 67 | addError("No encoder was configured. Use to specify the fully qualified class name of the encoder to use"); 68 | return; 69 | } 70 | 71 | checkProperties(); 72 | normalizeContentType(); 73 | 74 | encoder.start(); 75 | super.start(); 76 | } 77 | 78 | protected void checkProperties() { 79 | if (isStringEmptyOrNull(protocol)) { 80 | protocol = DEFAULT_PROTOCOL; 81 | addInfo(String.format(MSG_NOT_SET, "protocol", protocol)); 82 | } else { 83 | addInfo(String.format(MSG_USING, "protocol", protocol)); 84 | } 85 | 86 | if (isStringEmptyOrNull(url)) { 87 | url = DEFAULT_URL; 88 | addInfo(String.format(MSG_NOT_SET, "url", url)); 89 | } else { 90 | addInfo(String.format(MSG_USING, "url", url)); 91 | } 92 | 93 | if (isStringEmptyOrNull(path)) { 94 | path = DEFAULT_PATH; 95 | addInfo(String.format(MSG_NOT_SET, "path", path)); 96 | } else { 97 | addInfo(String.format(MSG_USING, "path", path)); 98 | } 99 | 100 | if (port == 0) { 101 | port = DEFAULT_PORT; 102 | addInfo(String.format(MSG_NOT_SET, "port", port)); 103 | } else { 104 | addInfo(String.format(MSG_USING, "port", port)); 105 | } 106 | 107 | if (isStringEmptyOrNull(contentType)) { 108 | contentType = DEFAULT_CONTENT_TYPE; 109 | addInfo(String.format(MSG_NOT_SET, "contentType", contentType)); 110 | } else { 111 | addInfo(String.format(MSG_USING, "contentType", contentType)); 112 | } 113 | 114 | if (reconnectDelay == 0) { 115 | reconnectDelay = DEFAULT_RECONNECT_DELAY; 116 | addInfo(String.format(MSG_NOT_SET, "reconnectDelay", reconnectDelay)); 117 | } else { 118 | addInfo(String.format(MSG_USING, "reconnectDelay", reconnectDelay)); 119 | } 120 | } 121 | 122 | protected void normalizeContentType() { 123 | if (contentType.equalsIgnoreCase("json")) { 124 | contentType = "application/json"; 125 | } else if (contentType.equalsIgnoreCase("xml")) { 126 | contentType = "application/xml"; 127 | } 128 | } 129 | 130 | @Override 131 | public void append(ILoggingEvent event) { 132 | try { 133 | HttpURLConnection conn = openConnection(); 134 | byte[] objEncoded = encoder.encode(event); 135 | transformHeaders(conn, objEncoded.length); 136 | sendBodyRequest(objEncoded, conn); 137 | } catch (IOException e) { 138 | addError("Error ocurred during the connection: ", e); 139 | reconnect(event); 140 | } 141 | } 142 | 143 | protected void transformHeaders(HttpURLConnection conn, int contentLength) { 144 | conn.setRequestProperty("Content-Type", contentType); 145 | conn.setRequestProperty("Content-length", Integer.toString(contentLength)); 146 | if (headers == null || headers.isEmpty()) { 147 | return; 148 | } 149 | 150 | JSONObject jObj = new JSONObject(headers); 151 | for (String key : jObj.keySet()) { 152 | String value = (String) jObj.get(key); 153 | conn.setRequestProperty(key, value); 154 | } 155 | } 156 | 157 | protected boolean sendNoBodyRequest(HttpURLConnection conn) throws IOException { 158 | return showResponse(conn); 159 | } 160 | 161 | protected boolean sendBodyRequest(byte[] objEncoded, HttpURLConnection conn) throws IOException { 162 | conn.setDoOutput(true); 163 | IOUtils.write(objEncoded, conn.getOutputStream()); 164 | return showResponse(conn); 165 | } 166 | 167 | protected void reconnect(ILoggingEvent event) { 168 | try { 169 | addInfo(String.format("Trying to reconnect in %s seconds", reconnectDelay)); 170 | Thread.sleep(Duration.ofSeconds(reconnectDelay).toMillis()); 171 | append(event); 172 | } catch (InterruptedException e1) { 173 | addError("Erro trying to reconnect: ", e1); 174 | e1.printStackTrace(); 175 | } 176 | } 177 | 178 | protected boolean showResponse(HttpURLConnection conn) throws IOException { 179 | int responseCode = conn.getResponseCode(); 180 | 181 | if (responseCode != HttpURLConnection.HTTP_OK) { 182 | addError(String.format("Error to send logs: %s", conn)); 183 | return false; 184 | } 185 | 186 | String response = IOUtils.toString(conn.getInputStream(), Charset.defaultCharset()); 187 | addInfo(String.format("Response result: %s", response)); 188 | return true; 189 | } 190 | 191 | protected HttpURLConnection openConnection() { 192 | HttpURLConnection conn = null; 193 | try { 194 | URL urlObj = new URL(protocol, url, port, path); 195 | addInfo("URL: " + urlObj.toString()); 196 | conn = (HttpURLConnection) urlObj.openConnection(); 197 | conn.setRequestMethod("POST"); 198 | return conn; 199 | } catch (Exception e) { 200 | addError("Error to open connection Exception: ", e); 201 | return null; 202 | } finally { 203 | try { 204 | if (conn != null) { 205 | conn.disconnect(); 206 | } 207 | } catch (Exception e) { 208 | addError("Error to open connection Exception: ", e); 209 | return null; 210 | } 211 | } 212 | } 213 | 214 | public Layout getLayout() { 215 | return layout; 216 | } 217 | 218 | public void setLayout(Layout layout) { 219 | this.layout = layout; 220 | } 221 | 222 | public Encoder getEncoder() { 223 | return encoder; 224 | } 225 | 226 | public void setEncoder(Encoder encoder) { 227 | this.encoder = encoder; 228 | } 229 | 230 | public String getUrl() { 231 | return url; 232 | } 233 | 234 | public void setUrl(String url) { 235 | this.url = url; 236 | } 237 | 238 | public String getContentType() { 239 | return contentType; 240 | } 241 | 242 | public void setContentType(String contentType) { 243 | this.contentType = contentType; 244 | } 245 | 246 | public String getBody() { 247 | return body; 248 | } 249 | 250 | public void setBody(String body) { 251 | this.body = body; 252 | } 253 | 254 | public String getHeaders() { 255 | return headers; 256 | } 257 | 258 | public void setHeaders(String headers) { 259 | this.headers = headers; 260 | } 261 | 262 | public int getPort() { 263 | return port; 264 | } 265 | 266 | public String getProtocol() { 267 | return protocol; 268 | } 269 | 270 | public void setProtocol(String protocol) { 271 | this.protocol = protocol; 272 | } 273 | 274 | public void setPort(int port) { 275 | this.port = port; 276 | } 277 | 278 | public String getPath() { 279 | return path; 280 | } 281 | 282 | public void setPath(String path) { 283 | this.path = path; 284 | } 285 | 286 | public int getReconnectDelay() { 287 | return reconnectDelay; 288 | } 289 | 290 | public void setReconnectDelay(int reconnectDelay) { 291 | this.reconnectDelay = reconnectDelay; 292 | } 293 | 294 | protected static boolean isStringEmptyOrNull(String value){ 295 | return value == null || value.isEmpty(); 296 | } 297 | } --------------------------------------------------------------------------------