Skip to content

Commit

Permalink
Merge pull request #22 from psquickitjayant/develop
Browse files Browse the repository at this point in the history
Added support for bulk mode
  • Loading branch information
varshneyjayant committed Jun 2, 2016
2 parents e472728 + b4dd17f commit 0b2b681
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 59 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ You can also use **layout** with in the Config to render logs according to your
<conversionPattern value="%date [%thread] %-5level %logger %message" />
</layout>

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

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


Add the following entry in your AssemblyInfo.cs
```
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
Expand Down
9 changes: 5 additions & 4 deletions source/log4net-loggly/ILogglyAppenderConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ public interface ILogglyAppenderConfig
string RootUrl { get; set; }
string InputKey { get; set; }
string UserAgent { get; set; }
string LogMode { get; set; }
int TimeoutInSeconds { get; set; }
string Tag { get; set; }
string LogicalThreadContextKeys { get; set; }
string GlobalContextKeys { get; set; }
}
string Tag { get; set; }
string LogicalThreadContextKeys { get; set; }
string GlobalContextKeys { get; set; }
}
}
121 changes: 83 additions & 38 deletions source/log4net-loggly/LogglyAppender.cs
Original file line number Diff line number Diff line change
@@ -1,57 +1,102 @@
using log4net.Appender;
using log4net.Core;
using System.Threading;
using System.Threading.Tasks;
using System;
using System.Collections.Generic;
using Timer = System.Timers;



namespace log4net.loggly
{
public class LogglyAppender : AppenderSkeleton
{
List<string> lstLogs = new List<string>();
string[] arr = new string[100];
public static readonly string InputKeyProperty = "LogglyInputKey";

public static ILogglyFormatter Formatter = new LogglyFormatter();
public static ILogglyClient Client = new LogglyClient();

private ILogglyAppenderConfig Config = new LogglyAppenderConfig();

public string RootUrl { set { Config.RootUrl = value; } }
public string InputKey { set { Config.InputKey = value; } }
public string UserAgent { set { Config.UserAgent = value; } }
public string LogMode { set { Config.LogMode = value; } }
public int TimeoutInSeconds { set { Config.TimeoutInSeconds = value; } }
public string Tag { set { Config.Tag = value; } }
public string LogicalThreadContextKeys { set { Config.LogicalThreadContextKeys = value; } }
public string GlobalContextKeys { set { Config.GlobalContextKeys = value; } }

protected override void Append(LoggingEvent loggingEvent)
{
SendLogAction(loggingEvent);
}

private void SendLogAction(LoggingEvent loggingEvent)
{
//we should always format event in the same thread as
//many properties used in the event are associated with the current thread
//like threadname, ndc stacks, threadcontent properties etc.

//initializing a string for the formatted log
string _formattedLog = string.Empty;

//if Layout is null then format the log from the Loggly Client
if (this.Layout == null)
{
Formatter.AppendAdditionalLoggingInformation(Config, loggingEvent);
_formattedLog = Formatter.ToJson(loggingEvent);
}
else
{
_formattedLog = Formatter.ToJson(RenderLoggingEvent(loggingEvent), loggingEvent.TimeStamp);
}

//sending _formattedLog to the async queue
ThreadPool.QueueUserWorkItem(x => Client.Send(Config, _formattedLog));
}
public string Tag { set { Config.Tag = value; } }
public string LogicalThreadContextKeys { set { Config.LogicalThreadContextKeys = value; } }
public string GlobalContextKeys { set { Config.GlobalContextKeys = value; } }

private LogglyAsyncHandler LogglyAsync;

public LogglyAppender()
{
LogglyAsync = new LogglyAsyncHandler();
Timer.Timer t = new Timer.Timer();
t.Interval = 20000;
t.Enabled = true;
t.Elapsed += t_Elapsed;
}

void t_Elapsed(object sender, Timer.ElapsedEventArgs e)
{
if (lstLogs.Count != 0)
{
SendAllEvents(lstLogs.ToArray());
}
}

protected override void Append(LoggingEvent loggingEvent)
{
SendLogAction(loggingEvent);
}

private void SendLogAction(LoggingEvent loggingEvent)
{
//we should always format event in the same thread as
//many properties used in the event are associated with the current thread
//like threadname, ndc stacks, threadcontent properties etc.

//initializing a string for the formatted log
string _formattedLog = string.Empty;

//if Layout is null then format the log from the Loggly Client
if (this.Layout == null)
{
Formatter.AppendAdditionalLoggingInformation(Config, loggingEvent);
_formattedLog = Formatter.ToJson(loggingEvent);
}
else
{
_formattedLog = Formatter.ToJson(RenderLoggingEvent(loggingEvent), loggingEvent.TimeStamp);
}

//check if logMode is bulk or inputs
if (Config.LogMode == "bulk/")
{
addToBulk(_formattedLog);
}
else if (Config.LogMode == "inputs/")
{
//sending _formattedLog to the async queue
LogglyAsync.PostMessage(_formattedLog, Config);
}
}

public void addToBulk(string log)
{
// store all events into a array max lenght is 100
lstLogs.Add(log.Replace("\n", ""));
if (lstLogs.Count == 100)
{
SendAllEvents(lstLogs.ToArray());
}
}

private void SendAllEvents(string[] events)
{
lstLogs.Clear();
String bulkLog = String.Join(System.Environment.NewLine, events);
LogglyAsync.PostMessage(bulkLog, Config);
}

}
}
}
31 changes: 21 additions & 10 deletions source/log4net-loggly/LogglyAppenderConfig.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
namespace log4net.loggly
{
public class LogglyAppenderConfig: ILogglyAppenderConfig
public class LogglyAppenderConfig : ILogglyAppenderConfig
{
private string _rootUrl;
private string _logMode;
public string RootUrl
{
get { return _rootUrl; }
Expand All @@ -14,9 +15,18 @@ public string RootUrl
{
_rootUrl += "/";
}
if (!_rootUrl.EndsWith("inputs/"))
}
}

public string LogMode
{
get { return _logMode; }
set
{
_logMode = value;
if (!_logMode.EndsWith("/"))
{
_rootUrl += "inputs/";
_logMode = _logMode.ToLower() + "/";
}
}
}
Expand All @@ -27,19 +37,20 @@ public string RootUrl

public int TimeoutInSeconds { get; set; }

public string Tag { get; set; }
public string Tag { get; set; }

public string LogicalThreadContextKeys { get; set; }
public string LogicalThreadContextKeys { get; set; }

public string GlobalContextKeys { get; set; }
public string GlobalContextKeys { get; set; }

public LogglyAppenderConfig()
public LogglyAppenderConfig()
{
UserAgent = "loggly-log4net-appender";
TimeoutInSeconds = 30;
Tag = "log4net";
LogicalThreadContextKeys = null;
GlobalContextKeys = null;
Tag = "log4net";
LogMode = "bulk";
LogicalThreadContextKeys = null;
GlobalContextKeys = null;
}
}
}
57 changes: 57 additions & 0 deletions source/log4net-loggly/LogglyAsyncHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System.Collections.Concurrent;
using System.Threading;

namespace log4net.loggly
{
class LogglyAsyncHandler
{
// Size of the internal event queue.
//protected const int QueueSize = 32768;
protected ILogglyAppenderConfig _config;

protected bool IsRunning = false;
//static list of all the queues the le appender might be managing.
private static ConcurrentBag<BlockingCollection<string>> _allQueues = new ConcurrentBag<BlockingCollection<string>>();

public static ILogglyClient Client = new LogglyClient();
public LogglyAsyncHandler()
{
Queue = new BlockingCollection<string>();
_allQueues.Add(Queue);
WorkerThread = new Thread(new ThreadStart(SendLogs));
WorkerThread.Name = "Loggly Log Appender";
WorkerThread.IsBackground = true;
}

protected readonly BlockingCollection<string> Queue;
protected Thread WorkerThread;

protected virtual void SendLogs()
{
if (this._config != null)
{
while (true)
{
var msg = Queue.Take();
Client.Send(this._config, msg);
}
}
}

public void PostMessage(string msg, ILogglyAppenderConfig config)
{
this._config = config;
if (!IsRunning)
{
WorkerThread.Start();
IsRunning = true;
}
if (!Queue.TryAdd(msg))
{
Queue.Take();
Queue.TryAdd(msg);
}
}
}

}
11 changes: 6 additions & 5 deletions source/log4net-loggly/LogglyBufferringAppender.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ public class LogglyBufferringAppender : BufferingAppenderSkeleton

private ILogglyAppenderConfig Config = new LogglyAppenderConfig();

public string RootUrl { set { Config.RootUrl = value; } }
public string InputKey { set { Config.InputKey = value; } }
public string UserAgent { set { Config.UserAgent = value; } }
public int TimeoutInSeconds { set { Config.TimeoutInSeconds = value; } }
public string Tag { set { Config.Tag = value; } }
public string RootUrl { set { Config.RootUrl = value; } }
public string InputKey { set { Config.InputKey = value; } }
public string UserAgent { set { Config.UserAgent = value; } }
public string LogMode { set { Config.LogMode = value; } }
public int TimeoutInSeconds { set { Config.TimeoutInSeconds = value; } }
public string Tag { set { Config.Tag = value; } }

protected override void Append(LoggingEvent loggingEvent)
{
Expand Down
4 changes: 2 additions & 2 deletions source/log4net-loggly/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("7.1.0.0")]
[assembly: AssemblyFileVersion("7.1.0.0")]
[assembly: AssemblyVersion("7.2.0.0")]
[assembly: AssemblyFileVersion("7.2.0.0")]
1 change: 1 addition & 0 deletions source/log4net-loggly/log4net-loggly.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<Compile Include="ILogglyAppenderConfig.cs" />
<Compile Include="ILogglyClient.cs" />
<Compile Include="LogglyAppenderConfig.cs" />
<Compile Include="LogglyAsyncHandler.cs" />
<Compile Include="LogglyBufferringAppender.cs" />
<Compile Include="LogglyClient.cs" />
<Compile Include="LogglyFormatter.cs" />
Expand Down

0 comments on commit 0b2b681

Please sign in to comment.