Skip to content
This repository has been archived by the owner on Apr 23, 2024. It is now read-only.

Commit

Permalink
Add unit tests for LogglyBatchAppender; Minor edits
Browse files Browse the repository at this point in the history
Added LogglyBatchAppenderTest, which interacts with a test HTTP
server (instead of Loggly) to run basic smoke tests.

Removed the toString() override, moving the debug info provided there
to its own debug function -- which is called only when the debug flag
is enabled.

Fixed raw-type warnings and javadoc typos.
  • Loading branch information
tony19 committed Feb 7, 2013
1 parent e77d0b0 commit 368d893
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 10 deletions.
6 changes: 6 additions & 0 deletions loggly/pom.xml
Expand Up @@ -38,6 +38,12 @@
<version>1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.simpleframework</groupId>
<artifactId>simple</artifactId>
<version>5.0.4</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Expand Up @@ -88,15 +88,15 @@
* <tr>
* <td>maxBucketSizeInKilobytes</td>
* <td>int</td>
* <td>Max size of each bucket. Default value: <code>1024</code> Kilobytes (1Mo).</td>
* <td>Max size of each bucket. Default value: <code>1024</code> Kilobytes (1MB).</td>
* </tr>
* <tr>
* <td>flushIntervalInSeconds</td>
* <td>int</td>
* <td>Interval of the buffer flush to Loggly API. Default value: <code>3</code>.</td>
* </tr>
* </table>
* Default configuration consumes up to 8 buffers of 1024 Kilobytes (1Mo) each which seemed very reasonable even for small JVMs.
* Default configuration consumes up to 8 buffers of 1024 Kilobytes (1MB) each, which seems very reasonable even for small JVMs.
* If logs are discarded, try first to shorten the <code>flushIntervalInSeconds</code> parameter to "2s" or event "1s".
* <p/>
* <h2>Configuration Sample</h2>
Expand Down Expand Up @@ -186,7 +186,7 @@ public void start() {
@Override
protected void onBucketDiscard(ByteArrayOutputStream discardedBucket) {
if (isDebug()) {
addInfo("Discard bucket - " + this);
addInfo("Discard bucket - " + getDebugInfo());
}
String s = new Timestamp(System.currentTimeMillis()) + " - OutputStream is full, discard previous logs" + LINE_SEPARATOR;
try {
Expand All @@ -200,7 +200,7 @@ protected void onBucketDiscard(ByteArrayOutputStream discardedBucket) {
@Override
protected void onBucketRoll(ByteArrayOutputStream rolledBucket) {
if (isDebug()) {
addInfo("Roll bucket - " + this);
addInfo("Roll bucket - " + getDebugInfo());
}
}

Expand Down Expand Up @@ -265,7 +265,7 @@ public void stop() {
@Override
public void processLogEntries() {
if (isDebug()) {
addInfo("processLogEntries() " + this);
addInfo("Process log entries - " + getDebugInfo());
}

outputStream.rollCurrentBucketIfNotEmpty();
Expand Down Expand Up @@ -402,9 +402,8 @@ public void setMaxBucketSizeInKilobytes(int maxBucketSizeInKilobytes) {
this.maxBucketSizeInKilobytes = maxBucketSizeInKilobytes;
}

@Override
public String toString() {
return "LogglyBatchAppender{" +
private String getDebugInfo() {
return "{" +
"sendDurationInMillis=" + TimeUnit.MILLISECONDS.convert(sendDurationInNanos.get(), TimeUnit.NANOSECONDS) +
", sendSuccessCount=" + sendSuccessCount +
", sendExceptionCount=" + sendExceptionCount +
Expand Down
142 changes: 142 additions & 0 deletions loggly/src/test/java/ch/qos/logback/ext/loggly/HttpTestServer.java
@@ -0,0 +1,142 @@
package ch.qos.logback.ext.loggly;

import java.io.IOException;
import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicInteger;

import org.simpleframework.http.Request;
import org.simpleframework.http.Response;
import org.simpleframework.http.core.Container;
import org.simpleframework.http.core.ContainerServer;
import org.simpleframework.transport.Server;
import org.simpleframework.transport.connect.Connection;
import org.simpleframework.transport.connect.SocketConnection;

/**
* HTTP test server that tracks the number of requests received
*/
public class HttpTestServer implements Container {
static private final int MAX_RXBUF_SIZE = 2048;
private int port;
private Connection connection;
private Server server;
AtomicInteger numRequests;

/**
* Initializes the HTTP server
* @param port
*/
public HttpTestServer(int port) {
this.port = port;
numRequests = new AtomicInteger(0);
}

/**
* Opens the HTTP server
* @throws IOException
*/
public void start() throws IOException {
stop();
this.server = new ContainerServer(this);
this.connection = new SocketConnection(server);
SocketAddress address = new InetSocketAddress(this.port);
this.connection.connect(address);
}

/**
* Closes the HTTP server
*/
public void stop() {
if (this.connection != null) {
try {
this.connection.close();
} catch (IOException e) {
}
}
}

/**
* Gets the number of requests received
* @return the request count
*/
public int requestCount() {
return numRequests.get();
}

/**
* Resets the request count
*/
public void clearRequests() {
numRequests.set(0);
}

/**
* Waits indefinitely for the specified number of requests to be received
* @param count the number of received requests to wait for
*/
public void waitForRequests(int count) {
waitForRequests(count, 0, 0);
}

/**
* Waits for the specified number of requests to be received
* @param count the number of received requests to wait for
* @param interval the wait time between polls, checking the receive count;
* use 0 to wait indefinitely
* @param maxPolls the maximum number of polls; use 0 for no limit
*/
public void waitForRequests(int count, long interval, int maxPolls) {
synchronized (this) {
while (requestCount() < count) {
System.out.println("requests " + requestCount() + "/" + count);
if (maxPolls > 0 && maxPolls-- > 0) {
break;
}
try {
this.wait(interval);
} catch (InterruptedException e) {
}
}
}
}

/**
* Handles incoming HTTP requests by responding with the
* message index and size of the received message.
* @see org.simpleframework.http.core.Container#handle(org.simpleframework.http.Request, org.simpleframework.http.Response)
*/
@Override
public void handle(Request request, Response response) {
try {
PrintStream body = response.getPrintStream();
long time = System.currentTimeMillis();

response.setValue("Content-Type", "text/html");
response.setValue("Server", "HttpTestServer/1.0 (Simple 4.0)");
response.setDate("Date", time);
response.setDate("Last-Modified", time);

ByteBuffer buf = ByteBuffer.allocate(MAX_RXBUF_SIZE);
int len = request.getByteChannel().read(buf);
int count = numRequests.incrementAndGet();

// warn if RX buffer exceeded (message truncated)
String warning = "";
if (len > MAX_RXBUF_SIZE) {
warning = "(" + (len - MAX_RXBUF_SIZE) + " bytes truncated)";
}

body.println("Request #" + count + "\n" + len + " bytes read" + warning);
body.close();

synchronized (this) {
notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,123 @@
/*
* Copyright 2012-2013 Ceki Gulcu, Les Hazlewood, et. al.
*
* Licensed 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 ch.qos.logback.ext.loggly;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.layout.EchoLayout;
import ch.qos.logback.core.status.OnConsoleStatusListener;

/**
* Tests the LogglyBatchAppender
*/
public class LogglyBatchAppenderTest {

static private final int PORT = 10800;
static private final int MAX_BUCKETS = 4;
static private final int BUCKET_KB_SIZE = 1;
static private final int MSG_SIZE = BUCKET_KB_SIZE * 1024;
static private HttpTestServer httpServer;
static private LogglyBatchAppender<String> appender;
static private LoggerContext context;

/**
* Starts the HTTP test server, initializes the appender,
* and creates a context with a status listener
* @throws IOException
*/
@BeforeClass
static public void beforeClass() throws IOException {
httpServer = new HttpTestServer(PORT);
httpServer.start();
context = new LoggerContext();
OnConsoleStatusListener.addNewInstanceToContext(context);
}

/**
* Shuts down the HTTP test server
*/
@AfterClass
static public void afterClass() {
httpServer.stop();
appender.stop();
}

@Before
public void before() throws UnknownHostException {
httpServer.clearRequests();

appender = new LogglyBatchAppender<String>();
appender.setContext(context);
appender.setEndpointUrl("http://" + InetAddress.getLocalHost().getHostAddress() + ":" + PORT + "/");

appender.setLayout(new EchoLayout<String>());
appender.setDebug(true);
appender.setMaxBucketSizeInKilobytes(BUCKET_KB_SIZE);
appender.setMaxNumberOfBuckets(MAX_BUCKETS);
appender.start();
}

@Test
public void starts() {
assertTrue(appender.isStarted());
}

private void appendFullBuckets(int count) {
for (int i = 0; i < count; i++) {
appender.doAppend(new String(new char[MSG_SIZE]).replace("\0", "X"));
}
}

@Test(timeout = 180000)
public void sendsOnlyWhenMaxBucketsFull() {
// assert nothing yet sent/received
assertEquals(0, appender.getSendSuccessCount());
assertEquals(0, httpServer.requestCount());

// send stuff and wait for it to be received
appendFullBuckets(MAX_BUCKETS);
httpServer.waitForRequests(MAX_BUCKETS);

// assert stuff sent/received
assertEquals(MAX_BUCKETS, appender.getSendSuccessCount());
assertEquals(MAX_BUCKETS, httpServer.requestCount());
}

@Test(timeout = 180000)
public void excessBucketsGetDiscarded() {
// assert nothing yet discarded (because nothing is yet sent)
assertEquals(0, appender.getDiscardedBucketsCount());

// send stuff and wait for it to be received
final int NUM_MSGS = 40;
appendFullBuckets(NUM_MSGS);
httpServer.waitForRequests(MAX_BUCKETS);

// assert excess buckets (those > MAX_BUCKETS) were discarded
assertEquals(NUM_MSGS - MAX_BUCKETS, appender.getDiscardedBucketsCount());
}
}
Expand Up @@ -45,15 +45,15 @@ public static void main(String[] args) throws Exception {
System.out.println("Generate " + file);
final OutputStream out = new FileOutputStream(file);

LogglyBatchAppender appender = new LogglyBatchAppender() {
LogglyBatchAppender<String> appender = new LogglyBatchAppender<String>() {
@Override
protected void processLogEntries(InputStream in) throws IOException {
// super.processLogEntries(in);
IoUtils.copy(in, out);
}
};
appender.setInputKey("YOUR LOGGLY INPUT KEY");
appender.setLayout(new EchoLayout());
appender.setLayout(new EchoLayout<String>());
appender.setDebug(true);

// Start
Expand Down

0 comments on commit 368d893

Please sign in to comment.