Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored the library #21

Merged
merged 12 commits into from Jan 29, 2019

Removed option to use /inputs endpoint

  • Loading branch information
Jiri Tomek
Jiri Tomek committed Jan 29, 2019
commit 3d56c39722401710ce50a232ae3a672e09c2136b
@@ -86,12 +86,6 @@ This flushes any pending messages.

## Advanced configuration

By default, library uses Loggly `/bulk` end point (https://www.loggly.com/docs/http-bulk-endpoint/). To use `/inputs` endpoint, add the following configuration to config file to `<appender>` section

```xml
<logMode value="inputs" />
```

Library by default serializes and sends 4 levels of inner exceptions in case of warn/error log. If you want to change this number just add following configuration to config file to `<appender>` section
```xml
<numberOfInnerExceptions value value="10"/>
@@ -89,7 +89,11 @@ static void Main(string[] argArray)
parent.Children = new List<Person> { child1, child2 };
log.Info(parent);

log.Debug("zzzz");
log.Debug(@"This
is
some
multiline
log");
log.InfoFormat("Loggly is the best {0} to collect Logs.", "service");
log.Info(new { type1 = "newcustomtype", value1 = "newcustomvalue" });
log.Info(new TestObject());
@@ -49,7 +49,6 @@ public void AppenderPropertiesSetConfigurationValues()
var appender = new LogglyAppender(config, Mock.Of<ILogglyFormatter>(), Mock.Of<ILogglyAsyncBuffer>());

appender.RootUrl = "root-url";
appender.SendMode = SendMode.Single;
appender.BufferSize = 123;
appender.CustomerToken = "test-token";
appender.GlobalContextKeys = "global-keys";
@@ -63,7 +62,6 @@ public void AppenderPropertiesSetConfigurationValues()
config.Should().BeEquivalentTo(new
{
RootUrl = "root-url",
SendMode = SendMode.Single,
BufferSize = 123,
CustomerToken = "test-token",
GlobalContextKeys = "global-keys",
@@ -75,19 +73,5 @@ public void AppenderPropertiesSetConfigurationValues()
UserAgent = "user-agent"
});
}

[Theory]
[InlineData("inputs", SendMode.Single)]
[InlineData("bulk", SendMode.Bulk)]
[InlineData("nonsense", SendMode.Bulk)]
public void LogModeSetsSendMode(string logMode, SendMode expectedSendMode)
{
var config = new Config();
var appender = new LogglyAppender(config, Mock.Of<ILogglyFormatter>(), Mock.Of<ILogglyAsyncBuffer>());

appender.LogMode = logMode;

config.SendMode.Should().Be(expectedSendMode);
}
}
}
@@ -36,7 +36,7 @@ public LogglyAsyncBufferTest()
public void Bulk_SendsMessagesWhenBufferSizeReached()
{
_config.BufferSize = 3;
ExpectBulkSends(1);
ExpectSends(1);
var buffer = new LogglyAsyncBuffer(_config, _clientMock.Object);

buffer.BufferForSend("test message 1");
@@ -53,11 +53,10 @@ public void Bulk_SendsMessagesWhenBufferSizeReached()
}

[Fact]
public void Bulk_DoesNotSendMessagesWhenBufferIsNotFullAndTimeIsNotExpired()
public void DoesNotSendMessagesWhenBufferIsNotFullAndTimeIsNotExpired()
{
_config.SendMode = SendMode.Bulk;
_config.BufferSize = 3;
ExpectBulkSends(1);
ExpectSends(1);
var buffer = new LogglyAsyncBuffer(_config, _clientMock.Object);

buffer.BufferForSend("test message 1");
@@ -69,12 +68,11 @@ public void Bulk_DoesNotSendMessagesWhenBufferIsNotFullAndTimeIsNotExpired()
}

[Fact]
public void Bulk_SendsMessagesWhenTimeExpires()
public void SendsMessagesWhenTimeExpires()
{
_config.SendMode = SendMode.Bulk;
_config.BufferSize = 3;
_config.SendInterval = TimeSpan.FromMilliseconds(500);
ExpectBulkSends(1);
ExpectSends(1);
var buffer = new LogglyAsyncBuffer(_config, _clientMock.Object);

buffer.BufferForSend("test message 1");
@@ -90,11 +88,10 @@ public void Bulk_SendsMessagesWhenTimeExpires()
}

[Fact]
public void Bulk_SendsAllAvailableMessages()
public void SendsAllAvailableMessages()
{
_config.SendMode = SendMode.Bulk;
_config.BufferSize = 3;
ExpectBulkSends(3);
ExpectSends(3);
var buffer = new LogglyAsyncBuffer(_config, _clientMock.Object);

buffer.BufferForSend("test message 1");
@@ -122,56 +119,20 @@ public void Bulk_SendsAllAvailableMessages()
}, "correct messages should be sent");
}

[Fact]
public void Single_SendsMessagesOneByOne()
{
_config.SendMode = SendMode.Single;
ExpectSingleSends(3);
var buffer = new LogglyAsyncBuffer(_config, _clientMock.Object);

buffer.BufferForSend("test message 1");
buffer.BufferForSend("test message 2");
buffer.BufferForSend("test message 3");

_allSentEvent.Wait(MaxWaitTime).Should().BeTrue("messages should be sent");
_sentMessages.Should().BeEquivalentTo(new[]
{
"test message 1",
"test message 2",
"test message 3"
}, "correct messages should be sent");
}

[Fact]
public void Single_DoesNotBufferMessages()
{
_config.SendMode = SendMode.Single;
_config.BufferSize = 100;
ExpectSingleSends(1);
var buffer = new LogglyAsyncBuffer(_config, _clientMock.Object);

buffer.BufferForSend("test message 1");

_allSentEvent.Wait(MaxWaitTime).Should().BeTrue("message should be sent");
_sentMessages.Should().BeEquivalentTo(new[]
{
"test message 1"
}, "correct message should be sent");
}

[Fact]
public void DiscardsOldestMessagesIfMaxQueueSizeIsSet()
{
_config.SendMode = SendMode.Single;
_config.MaxLogQueueSize = 5;
ExpectSingleSends(1);
ExpectSends(1);
var buffer = new LogglyAsyncBuffer(_config, _clientMock.Object);

_allowSendingEvent.Reset(); // block after first message sending
buffer.BufferForSend("test message 1");
// trigger send without waiting for full buffer
buffer.Flush(TimeSpan.FromMilliseconds(10));
_allSentEvent.Wait(MaxWaitTime).Should().BeTrue("first message should be already sent");

ExpectSingleSends(_config.MaxLogQueueSize);
ExpectSends(1);

buffer.BufferForSend("test message 2");
buffer.BufferForSend("test message 3");
@@ -202,9 +163,8 @@ public void DiscardsOldestMessagesIfMaxQueueSizeIsSet()
[Fact]
public void Flush_FlushesPendingMessages()
{
_config.SendMode = SendMode.Bulk;
_config.BufferSize = 3;
ExpectBulkSends(1);
ExpectSends(1);
var buffer = new LogglyAsyncBuffer(_config, _clientMock.Object);

buffer.BufferForSend("test message 1");
@@ -222,7 +182,6 @@ public void Flush_FlushesPendingMessages()
[Fact]
public void Flush_ReturnsTrueIfAllMessagesAreSent()
{
_config.SendMode = SendMode.Bulk;
_config.BufferSize = 3;
var buffer = new LogglyAsyncBuffer(_config, _clientMock.Object);

@@ -237,9 +196,8 @@ public void Flush_ReturnsTrueIfAllMessagesAreSent()
[Fact]
public void Flush_ReturnsFalseIfNotAllMessagesAreSent()
{
_config.SendMode = SendMode.Bulk;
_config.BufferSize = 3;
ExpectBulkSends(1);
ExpectSends(1);
var buffer = new LogglyAsyncBuffer(_config, _clientMock.Object);

// block sending
@@ -258,13 +216,12 @@ public void SentBulkIsLimitedByMaxBulkSize()
{
// message of 10 bytes, buffer for 10 messages = 100 bytes
// max bulk size se to 30 -> bulk size should be limited by this number
_config.SendMode = SendMode.Bulk;
_config.MaxBulkSizeBytes = 30;
_config.BufferSize = 10;
var oneMessageSize = 10;
var oneMessage = new String('x', oneMessageSize);

ExpectBulkSends(1);
ExpectSends(1);

var buffer = new LogglyAsyncBuffer(_config, _clientMock.Object);

@@ -282,7 +239,7 @@ public void SentBulkIsLimitedByMaxBulkSize()
}, "correct messages should be sent");
}

private void ExpectBulkSends(int numberOfSends)
private void ExpectSends(int numberOfSends)
{
_allSentEvent = new CountdownEvent(numberOfSends);
_clientMock.Setup(x => x.Send(It.IsAny<string[]>(), It.IsAny<int>()))
@@ -293,17 +250,5 @@ private void ExpectBulkSends(int numberOfSends)
_allowSendingEvent.WaitOne();
});
}

private void ExpectSingleSends(int numberOfSends)
{
_allSentEvent = new CountdownEvent(numberOfSends);
_clientMock.Setup(x => x.Send(It.IsAny<string>()))
.Callback<string>(m =>
{
_sentMessages.Add(m);
_allSentEvent.Signal();
_allowSendingEvent.WaitOne();
});
}
}
}
@@ -13,7 +13,7 @@ public class LogglyClientTest
{
private MemoryStream _messageStream;
private string _usedUrl;
private Mock<WebRequest> _webRequestMock;
private readonly Mock<WebRequest> _webRequestMock;

public LogglyClientTest()
{
@@ -36,24 +36,21 @@ public LogglyClientTest()
};
}

[Theory]
[InlineData(SendMode.Single, "inputs")]
[InlineData(SendMode.Bulk, "bulk")]
public void SendsToProperUrlBasedOnMode(SendMode mode, string expectedPath)
[Fact]
public void SendsToProperUrl()
{
var config = new Config
{
RootUrl = "https://logs01.loggly.test",
CustomerToken = "customer-token",
Tag = "tag1,tag2",
UserAgent = "user-agent",
SendMode = mode
UserAgent = "user-agent"
};
var client = new LogglyClient(config);

client.Send(new[] { "test message" }, 1);

_usedUrl.Should().Be($"https://logs01.loggly.test/{expectedPath}/customer-token/tag/tag1,tag2,user-agent");
_usedUrl.Should().Be($"https://logs01.loggly.test/bulk/customer-token/tag/tag1,tag2,user-agent");
}

[Fact]
@@ -13,7 +13,6 @@ public Config()
TimeoutInSeconds = 30;
MaxSendRetries = 3;
Tag = "log4net";
SendMode = SendMode.Bulk;
LogicalThreadContextKeys = null;
GlobalContextKeys = null;
BufferSize = 500;
@@ -35,21 +34,15 @@ public Config()
/// Max size of whole event sent to Loggly in bytes
/// </summary>
public int MaxEventSizeBytes { get; set; }

/// <summary>
/// Max size ot one bulk of events sent to Loggly in bytes
/// </summary>
public int MaxBulkSizeBytes { get; set; }

/// <summary>
/// URL where the logs are sent
/// </summary>
public string RootUrl { get; set; }
/// <summary>
/// Mode of sending logs.
/// </summary>
public SendMode SendMode { get; set; }
/// <summary>
/// Customer token used to send the logs
/// </summary>
public string CustomerToken { get; set; }
@@ -9,7 +9,7 @@ public class LogglyAppender : AppenderSkeleton
private ILogglyFormatter _formatter;
private ILogglyAsyncBuffer _buffer;
private readonly Config _config;
private ILogglyClient _client = null;
private ILogglyClient _client;

public LogglyAppender()
{
@@ -88,18 +88,6 @@ public string UserAgent
set => _config.UserAgent = value;
}

public string LogMode
{
get => SendMode == SendMode.Single ? "inputs" : "bulk";
set => SendMode = value == "inputs" ? SendMode.Single : SendMode.Bulk;
}

public SendMode SendMode
{
get => _config.SendMode;
set => _config.SendMode = value;
}

public int TimeoutInSeconds
{
get => _config.TimeoutInSeconds;
@@ -35,7 +35,7 @@ public void BufferForSend(string message)
_messages.Enqueue(message);

// initiate send if sending one by one or if there is already enough messages for batch
if (_config.SendMode == SendMode.Single || _messages.Count >= _config.BufferSize)
if (_messages.Count >= _config.BufferSize)
{
_readyToSendEvent.Set();
}
@@ -70,37 +70,6 @@ public bool Flush(TimeSpan maxWait)
}

private void DoSend()
{
if (_config.SendMode == SendMode.Single)
{
DoSendSingle();
}
else
{
DoSendBulks();
}
}

private void DoSendSingle()
{
// WaitAny returns index of completed task or WaitTimeout value (number) in case of timeout.
// We want to continue unless _stopEvent was set, so unless returned value is 0 - index of _stopEvent
var handles = new WaitHandle[] {_stopEvent, _readyToSendEvent, _flushingEvent};

while (WaitHandle.WaitAny(handles, _config.SendInterval) != 0)
{
// consume all we can
_sendInProgress = true;
while (_messages.TryDequeue(out var message))
{
_client.Send(message);
}
_sendInProgress = false;
_readyToSendEvent.Reset();
}
}

private void DoSendBulks()
{
var sendBuffer = new string[_config.BufferSize];

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.