diff --git a/README.md b/README.md
index 9a18d0b57f..9df61cad75 100644
--- a/README.md
+++ b/README.md
@@ -92,6 +92,13 @@ Twilio.setEdge("sydney");
This will result in the `hostname` transforming from `api.twilio.com` to `api.sydney.au1.twilio.com`.
+### Enable Debug Logging
+In order to enable debug logging, create a configuration file named log4j2.xml that defines the logger at the root level to at least 'debug'. An example of the configuration file can be found [here](src/main/java/com/twilio/example/log4j2.xml). For more configuration options please see the log4j configuration [documentation](https://logging.apache.org/log4j/2.x/manual/configuration.html).
+```java
+Twilio.init(accountSid, authToken);
+Twilio.setLoggerConfiguration("path/to/log4j2.xml");
+```
+
### Environment Variables
`twilio-java` supports the credentials, region, and edge values stored in the following environment variables:
@@ -139,7 +146,7 @@ try {
new PhoneNumber("+15559994321"), // From number
"Hello world!" // SMS body
).create();
-
+
System.out.println(message.getSid());
} catch (final ApiException e) {
System.err.println(e);
diff --git a/pom.xml b/pom.xml
index ed2976911a..20516d147f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -238,6 +238,16 @@
3.4.1
test
+
+ org.apache.logging.log4j
+ log4j-api
+ 2.14.0
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.14.0
+
@@ -382,4 +392,4 @@
oss-parent
7
-
\ No newline at end of file
+
diff --git a/src/main/java/com/twilio/Twilio.java b/src/main/java/com/twilio/Twilio.java
index cb35cf6341..6820838f8c 100644
--- a/src/main/java/com/twilio/Twilio.java
+++ b/src/main/java/com/twilio/Twilio.java
@@ -12,6 +12,10 @@
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.io.File;
+
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.LogManager;
/**
* Singleton class to initialize Twilio environment.
@@ -150,6 +154,19 @@ public static synchronized void setEdge(final String edge) {
Twilio.edge = edge;
}
+ /**
+ * Set the logger configuration file path.
+ *
+ * @param filePath path to logging configuration file
+ * @param loggerContext defaults to false to get the appropriate logger context for the caller.
+ */
+ public static synchronized void setLoggerConfiguration(final String filePath, final boolean... loggerContext) {
+ boolean logContext = (loggerContext.length >= 1) ? loggerContext[0] : false;
+ LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(logContext);
+ File file = new File(filePath);
+ context.setConfigLocation(file.toURI());
+ }
+
/**
* Returns (and initializes if not initialized) the Twilio Rest Client.
*
diff --git a/src/main/java/com/twilio/example/log4j2.xml b/src/main/java/com/twilio/example/log4j2.xml
new file mode 100644
index 0000000000..b29b207aca
--- /dev/null
+++ b/src/main/java/com/twilio/example/log4j2.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/twilio/http/TwilioRestClient.java b/src/main/java/com/twilio/http/TwilioRestClient.java
index 61acfc6679..fcf91d4ad1 100644
--- a/src/main/java/com/twilio/http/TwilioRestClient.java
+++ b/src/main/java/com/twilio/http/TwilioRestClient.java
@@ -4,6 +4,12 @@
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.util.function.Predicate;
+import java.util.Map;
+import java.util.List;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
public class TwilioRestClient {
@@ -19,6 +25,7 @@ public class TwilioRestClient {
private final String region;
private final String edge;
private final HttpClient httpClient;
+ private static final Logger logger = LogManager.getLogger();
private TwilioRestClient(Builder b) {
this.username = b.username;
@@ -50,7 +57,16 @@ public Response request(final Request request) {
if (edge != null)
request.setEdge(edge);
- return httpClient.reliableRequest(request);
+ logRequest(request);
+ Response response = httpClient.reliableRequest(request);
+ logger.debug("status code: " + response.getStatusCode());
+ org.apache.http.Header[] responseHeaders = response.getHeaders();
+ logger.debug("response headers:");
+ for (int i = 0; i < responseHeaders.length; i++) {
+ logger.debug(responseHeaders[i]);
+ }
+
+ return response;
}
public String getAccountSid() {
@@ -126,4 +142,29 @@ public TwilioRestClient build() {
}
}
+ /**
+ * Logging debug information about HTTP request.
+ */
+ public void logRequest(final Request request) {
+ logger.debug("-- BEGIN Twilio API Request --");
+ logger.debug("request method: " + request.getMethod());
+ logger.debug("request URL: " + request.getUrl());
+ final Map> queryParams = request.getQueryParams();
+ final Map> headerParams = request.getHeaderParams();
+
+ if (!queryParams.isEmpty()) {
+ logger.debug("query parameters: " + queryParams);
+ }
+
+ if (!headerParams.isEmpty()) {
+ logger.debug("header parameters: ");
+ for (String key : headerParams.keySet()) {
+ if (!key.toLowerCase().contains("authorization")) {
+ logger.debug(key + ": " + headerParams.get(key));
+ }
+ }
+ }
+ logger.debug("-- END Twilio API Request --");
+ }
+
}
diff --git a/src/test/java/com/twilio/http/LoggingTest.java b/src/test/java/com/twilio/http/LoggingTest.java
new file mode 100644
index 0000000000..9760ff536d
--- /dev/null
+++ b/src/test/java/com/twilio/http/LoggingTest.java
@@ -0,0 +1,59 @@
+package com.twilio.http;
+
+import com.twilio.Twilio;
+import com.twilio.rest.Domains;
+import com.twilio.rest.api.v2010.account.Message;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.Assert;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+public class LoggingTest {
+ private ByteArrayOutputStream output;
+ private PrintStream originalStream;
+
+ @Before
+ public void setUp() throws Exception {
+ Twilio.init("AC123", "AUTH TOKEN");
+ }
+
+ public void logCapturingSetup() {
+ output = new ByteArrayOutputStream();
+ PrintStream outputStream = new PrintStream(output);
+ originalStream = System.out;
+ System.setOut(outputStream);
+ }
+
+ public void finishLogCapturingSetup(Request request) {
+ TwilioRestClient twilioRestClient = Twilio.getRestClient();
+ twilioRestClient.logRequest(request);
+ System.out.flush();
+ System.setOut(originalStream);
+ }
+
+ @Test
+ public void testDebugLogging() {
+ logCapturingSetup();
+ Twilio.setLoggerConfiguration("src/main/java/com/twilio/example/log4j2.xml");
+ final Request request = new Request(HttpMethod.GET, Domains.API.toString(),
+ "/2010-04-01/Accounts/AC123/Messages/MM123.json");
+ request.addHeaderParam("Authorization", "authorization value");
+ request.addHeaderParam("Test Header", "test value");
+ finishLogCapturingSetup(request);
+ Assert.assertTrue(output.toString().contains("GET"));
+ Assert.assertFalse(output.toString().contains("Authorization"));
+ }
+
+ @Test
+ public void testUsingDefaultConfigurationFileDebugLogging() {
+ logCapturingSetup();
+ final Request request = new Request(HttpMethod.GET, Domains.API.toString(),
+ "/2010-04-01/Accounts/AC123/Messages/MM123.json");
+ request.addHeaderParam("Authorization", "authorization value");
+ request.addHeaderParam("Test Header", "test value");
+ finishLogCapturingSetup(request);
+ Assert.assertTrue(output.toString().isEmpty());
+ }
+}