Skip to content

Commit

Permalink
Upgrade dependencies & Support Exceptions
Browse files Browse the repository at this point in the history
NLog 4.2.3
Elasticsearch.Net 1.8.0
Tidy existing code
  • Loading branch information
markmcdowell committed Mar 25, 2016
1 parent 899ff0b commit 6209dd0
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 108 deletions.
40 changes: 0 additions & 40 deletions src/NLog.Targets.ElasticSearch.Tests/ElasticSearchTargetTests.cs

This file was deleted.

64 changes: 64 additions & 0 deletions src/NLog.Targets.ElasticSearch.Tests/IntegrationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using NLog.Config;
using NUnit.Framework;

namespace NLog.Targets.ElasticSearch.Tests
{
[TestFixture, Explicit]
public class IntegrationTests
{
[Test]
public void SimpleLogTest()
{
var elasticTarget = new ElasticSearchTarget();

var rule = new LoggingRule("*", elasticTarget);
rule.EnableLoggingForLevel(LogLevel.Info);

var config = new LoggingConfiguration();
config.LoggingRules.Add(rule);

LogManager.Configuration = config;

var logger = LogManager.GetLogger("Example");

logger.Info("Hello elasticsearch");

LogManager.Flush();
}

[Test]
public void ExceptionTest()
{
var elasticTarget = new ElasticSearchTarget();

var rule = new LoggingRule("*", elasticTarget);
rule.EnableLoggingForLevel(LogLevel.Error);

var config = new LoggingConfiguration();
config.LoggingRules.Add(rule);

LogManager.Configuration = config;

var logger = LogManager.GetLogger("Example");

var exception = new ArgumentNullException("argument");

logger.Error(exception, "An exception occured");

LogManager.Flush();
}

[Test]
public void ReadFromConfigTest()
{
LogManager.Configuration = new XmlLoggingConfiguration("NLog.Targets.ElasticSearch.Tests.dll.config");

var logger = LogManager.GetLogger("Example");

logger.Info("Hello elasticsearch");

LogManager.Flush();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="NLog">
<HintPath>..\packages\NLog.3.1.0.0\lib\net40\NLog.dll</HintPath>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NLog.4.2.3\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
<Reference Include="nunit.framework, Version=3.2.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NUnit.3.2.0\lib\net40\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
Expand All @@ -45,7 +47,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ElasticSearchTargetTests.cs" />
<Compile Include="IntegrationTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions src/NLog.Targets.ElasticSearch.Tests/packages.config
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NLog" version="3.1.0.0" targetFramework="net40" />
<package id="NUnit" version="2.6.3" targetFramework="net40" />
<package id="NLog" version="4.2.3" targetFramework="net40" />
<package id="NUnit" version="3.2.0" targetFramework="net40" />
</packages>
123 changes: 72 additions & 51 deletions src/NLog.Targets.ElasticSearch/ElasticSearchTarget.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using Elasticsearch.Net;
using Elasticsearch.Net.Connection;
Expand All @@ -13,71 +12,83 @@
namespace NLog.Targets.ElasticSearch
{
[Target("ElasticSearch")]
public class ElasticSearchTarget : TargetWithLayout
public class ElasticSearchTarget : TargetWithLayout, IElasticSearchTarget
{
private IElasticsearchClient _client;
private List<string> _excludedProperties = new List<string>(new[] { "CallerMemberName", "CallerFilePath", "CallerLineNumber", "MachineName", "ThreadId" });
private List<string> _excludedProperties = new List<string>(new[] { "CallerMemberName", "CallerFilePath", "CallerLineNumber", "MachineName", "ThreadId" });

/// <summary>
/// Gets or sets a connection string name to retrieve the Uri from.
///
/// Use as an alternative to Uri
/// </summary>
public string ConnectionStringName { get; set; }

/// <summary>
/// Gets or sets the elasticsearch uri, can be multiple comma separated.
/// </summary>
public string Uri { get; set; }

/// <summary>
/// Gets or sets the name of the elasticsearch index to write to.
/// </summary>
public Layout Index { get; set; }

/// <summary>
/// Gets or sets whether to include all properties of the log event in the document
/// </summary>
public bool IncludeAllProperties { get; set; }

/// <summary>
/// Gets or sets a comma separated list of excluded properties when setting <see cref="IElasticSearchTarget.IncludeAllProperties"/>
/// </summary>
public string ExcludedProperties { get; set; }

/// <summary>
/// Gets or sets the document type for the elasticsearch index.
/// </summary>
[RequiredParameter]
public Layout DocumentType { get; set; }

[ArrayParameter(typeof(ElasticSearchField), "field")]
public IList<ElasticSearchField> Fields { get; private set; }
/// <summary>
/// Gets or sets a list of additional fields to add to the elasticsearch document.
/// </summary>
[ArrayParameter(typeof(Field), "field")]
public IList<Field> Fields { get; set; }

/// <summary>
/// Gets or sets an alertnative serializer for the elasticsearch client to use.
/// </summary>
public IElasticsearchSerializer ElasticsearchSerializer { get; set; }

/// <summary>
/// Defines if exception will be rethrown.
/// Gets or sets if exceptions will be rethrown.
///
/// Set it to true if ElasticSearchTarget target is used within FallbackGroup target (https://github.com/NLog/NLog/wiki/FallbackGroup-target).
/// </summary>
public bool ThrowExceptions { get; set; }

public ElasticSearchTarget()
{
Name = "ElasticSearch";
Uri = "http://localhost:9200";
DocumentType = "logevent";
Index = "logstash-${date:format=yyyy.MM.dd}";
Fields = new List<ElasticSearchField>();
Fields = new List<Field>();
}

protected override void InitializeTarget()
{
base.InitializeTarget();

var uri = GetConnectionString(ConnectionStringName) ?? Uri;
var nodes = uri.Split(',').Select(url => new Uri(url));
var uri = ConnectionStringName.GetConnectionString() ?? Uri;
var nodes = uri.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(url => new Uri(url));
var connectionPool = new StaticConnectionPool(nodes);
var config = new ConnectionConfiguration(connectionPool);
_client = new ElasticsearchClient(config, serializer:ElasticsearchSerializer);

if (!String.IsNullOrEmpty(ExcludedProperties))
_excludedProperties = new List<string>(ExcludedProperties.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries));
}

private string GetConnectionString(string name)
{
string value = GetEnvironmentVariable(name);
if (!String.IsNullOrEmpty(value))
return value;

var connectionString = ConfigurationManager.ConnectionStrings[name];
return connectionString != null ? connectionString.ConnectionString : null;
}

private string GetEnvironmentVariable(string name) {
if (String.IsNullOrEmpty(name))
return null;

return Environment.GetEnvironmentVariable(name);
if (!string.IsNullOrEmpty(ExcludedProperties))
_excludedProperties = ExcludedProperties.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
}

protected override void Write(AsyncLogEventInfo logEvent)
Expand All @@ -92,17 +103,41 @@ protected override void Write(AsyncLogEventInfo[] logEvents)

private void SendBatch(IEnumerable<AsyncLogEventInfo> events)
{
var logEvents = events.Select(e => e.LogEvent);
try
{
var logEvents = events.Select(e => e.LogEvent);

var payload = FormPayload(logEvents);

var result = _client.Bulk<byte[]>(payload);
if (!result.Success)
InternalLogger.Error("Failed to send log messages to elasticsearch: status={0}, message=\"{1}\"", result.HttpStatusCode, result.OriginalException.Message);
}
catch (Exception ex)
{
InternalLogger.Error("Error while sending log messages to elasticsearch: message=\"{0}\"", ex.Message);

if (ThrowExceptions)
throw;
}
}

private object FormPayload(IEnumerable<LogEventInfo> logEvents)
{
var payload = new List<object>();

foreach (var logEvent in logEvents)
{
var document = new Dictionary<string, object>();
document.Add("@timestamp", logEvent.TimeStamp);
document.Add("level", logEvent.Level.Name);
var document = new Dictionary<string, object>
{
{"@timestamp", logEvent.TimeStamp},
{"level", logEvent.Level.Name},
{"message", Layout.Render(logEvent)}
};

if (logEvent.Exception != null)
document.Add("exception", logEvent.Exception.ToString());
document.Add("message", Layout.Render(logEvent));
document.Add("exception", logEvent.Exception);

foreach (var field in Fields)
{
var renderedField = field.Layout.Render(logEvent);
Expand All @@ -112,11 +147,9 @@ private void SendBatch(IEnumerable<AsyncLogEventInfo> events)

if (IncludeAllProperties)
{
foreach (var p in logEvent.Properties.Where(p => !_excludedProperties.Contains(p.Key)))
foreach (var p in logEvent.Properties.Where(p => !_excludedProperties.Contains(p.Key.ToString()))
.Where(p => !document.ContainsKey(p.Key.ToString())))
{
if (document.ContainsKey(p.Key.ToString()))
continue;

document[p.Key.ToString()] = p.Value;
}
}
Expand All @@ -128,19 +161,7 @@ private void SendBatch(IEnumerable<AsyncLogEventInfo> events)
payload.Add(document);
}

try
{
var result = _client.Bulk<byte[]>(payload);
if (!result.Success)
InternalLogger.Error("Failed to send log messages to ElasticSearch: status={0} message=\"{1}\"", result.HttpStatusCode, result.OriginalException.Message);
}
catch (Exception ex)
{
InternalLogger.Error("Error while sending log messages to ElasticSearch: message=\"{0}\"", ex.Message);
//rethrow exception if required
if (ThrowExceptions)
throw;
}
return payload;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
namespace NLog.Targets.ElasticSearch
{
[NLogConfigurationItem]
public class ElasticSearchField
public class Field
{
public ElasticSearchField()
public Field()
{
LayoutType = typeof (string);
}
Expand Down
Loading

0 comments on commit 6209dd0

Please sign in to comment.