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

fix: properly handle remote hostname #30

Merged
merged 1 commit into from
Sep 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ bld/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# JetBrains config directory
.idea/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
Expand Down
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ This project adheres to [Semantic Versioning](http://semver.org/) and is followi

## Unreleased

### :syringe: Fixed

- [#29](https://github.com/FantasticFiasco/serilog-sinks-udp/issues/29) Fix remote hostname implementation bug (contribution by [Nisheeth Barthwal](https://github.com/nbaztec))

## [4.1.0] - 2018-06-06

### :zap: Added
Expand All @@ -32,13 +36,13 @@ This project adheres to [Semantic Versioning](http://semver.org/) and is followi

### :zap: Added

- Text formatter complient with log4net XML schema, thus compatible with [Log4View](http://www.log4view.com) (contribution by [jvanrhyn](https://github.com/jvanrhyn))
- Text formatter compliant with log4net XML schema, thus compatible with [Log4View](http://www.log4view.com) (contribution by [jvanrhyn](https://github.com/jvanrhyn))

## [3.2.0] - 2017-08-26

### :zap: Added

- Text formatter complient with log4j XML schema, thus compatible with [Log2Console](https://github.com/Statyk7/log2console)
- Text formatter compliant with log4j XML schema, thus compatible with [Log2Console](https://github.com/Statyk7/log2console)

## [3.1.0] - 2017-08-20

Expand Down
5 changes: 4 additions & 1 deletion serilog-sinks-udp.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -365,4 +365,7 @@ public void SetUp()
<s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=FB31D57BA1B8194CA27B673C3340FD7B/Field/=type/Order/@EntryValue">0</s:Int64>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=FB31D57BA1B8194CA27B673C3340FD7B/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=FB31D57BA1B8194CA27B673C3340FD7B/Scope/=C3001E7C0DA78E4487072B7E050D86C5/CustomProperties/=minimumLanguageVersion/@EntryIndexedValue">2.0</s:String>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=FB31D57BA1B8194CA27B673C3340FD7B/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String></wpf:ResourceDictionary>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=FB31D57BA1B8194CA27B673C3340FD7B/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=datagram/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=multicast/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Serilog/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
171 changes: 122 additions & 49 deletions src/Serilog.Sinks.Udp/LoggerSinkConfigurationExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
// Copyright 2015-2018 Serilog Contributors
//
//
// 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.

using System;
using System.ComponentModel;
using System.Net;
using Serilog.Configuration;
using Serilog.Events;
Expand All @@ -32,11 +31,45 @@ public static class LoggerSinkConfigurationExtensions
{
private const string DefaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}";

// NOTE:
// This overload that accepts the remote address as a string must come first in the
// class, otherwise Serilog.Settings.Configuration won't work.

/// <summary>
/// Extension method providing JSON support via
/// <a href="https://github.com/serilog/serilog-settings-configuration">Serilog.Settings.Configuration</a>.
/// Adds a sink that sends log events as UDP packages over the network.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
/// <param name="sinkConfiguration">
/// Logger sink configuration.
/// </param>
/// <param name="remoteAddress">
/// The hostname of the remote host or multicast group to which the UDP client should sent
/// the logging event.
/// </param>
/// <param name="remotePort">
/// The TCP port of the remote host or multicast group to which the UDP client should sent
/// the logging event.
/// </param>
/// <param name="localPort">
/// The TCP port from which the UDP client will communicate. The default is 0 and will
/// cause the UDP client not to bind to a local port.
/// </param>
/// <param name="restrictedToMinimumLevel">
/// The minimum level for events passed through the sink. The default is
/// <see cref="LevelAlias.Minimum"/>.
/// </param>
/// <param name="levelSwitch">
/// A switch allowing the pass-through minimum level to be changed at runtime.
/// </param>
/// <param name="outputTemplate">
/// A message template describing the format used to write to the sink. The default is
/// "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}".
/// </param>
/// <param name="formatProvider">
/// Supplies culture-specific formatting information, or null.
/// </param>
/// <returns>
/// Logger configuration, allowing configuration to continue.
/// </returns>
public static LoggerConfiguration Udp(
this LoggerSinkConfiguration sinkConfiguration,
string remoteAddress,
Expand All @@ -47,21 +80,27 @@ public static LoggerConfiguration Udp(
string outputTemplate = DefaultOutputTemplate,
IFormatProvider formatProvider = null)
{
if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));
if (outputTemplate == null) throw new ArgumentNullException(nameof(outputTemplate));

var formatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);

return Udp(
sinkConfiguration,
remoteAddress.ToIPAddress(),
remoteAddress,
remotePort,
formatter,
localPort,
restrictedToMinimumLevel,
levelSwitch,
outputTemplate,
formatProvider);
levelSwitch);
}

/// <summary>
/// Adds a sink that sends log events as UDP packages over the network.
/// </summary>
/// <param name="sinkConfiguration">Logger sink configuration.</param>
/// <param name="sinkConfiguration">
/// Logger sink configuration.
/// </param>
/// <param name="remoteAddress">
/// The <see cref="IPAddress"/> of the remote host or multicast group to which the UDP
/// client should sent the logging event.
Expand All @@ -88,7 +127,9 @@ public static LoggerConfiguration Udp(
/// <param name="formatProvider">
/// Supplies culture-specific formatting information, or null.
/// </param>
/// <returns>Logger configuration, allowing configuration to continue.</returns>
/// <returns>
/// Logger configuration, allowing configuration to continue.
/// </returns>
public static LoggerConfiguration Udp(
this LoggerSinkConfiguration sinkConfiguration,
IPAddress remoteAddress,
Expand All @@ -99,27 +140,54 @@ public static LoggerConfiguration Udp(
string outputTemplate = DefaultOutputTemplate,
IFormatProvider formatProvider = null)
{
if (sinkConfiguration == null)
throw new ArgumentNullException(nameof(sinkConfiguration));
if (outputTemplate == null)
throw new ArgumentNullException(nameof(outputTemplate));

var formatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
return Udp(
sinkConfiguration,
remoteAddress,
remoteAddress.ToString(),
remotePort,
formatter,
localPort,
restrictedToMinimumLevel,
levelSwitch);
levelSwitch,
outputTemplate,
formatProvider
);
}

// NOTE:
// This overload that accepts the remote address as a string must come first in the
// class, otherwise Serilog.Settings.Configuration won't work.

/// <summary>
/// Extension method providing JSON support via
/// <a href="https://github.com/serilog/serilog-settings-configuration">Serilog.Settings.Configuration</a>.
/// Adds a sink that sends log events as UDP packages over the network.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
/// <param name="sinkConfiguration">
/// Logger sink configuration.
/// </param>
/// <param name="remoteAddress">
/// The hostname of the remote host or multicast group to which the UDP client should sent
/// the logging event.
/// </param>
/// <param name="remotePort">
/// The TCP port of the remote host or multicast group to which the UDP client should sent
/// the logging event.
/// </param>
/// <param name="formatter">
/// Controls the rendering of log events into text, for example to log JSON. To control
/// plain text formatting, use the overload that accepts an output template.
/// </param>
/// <param name="localPort">
/// The TCP port from which the UDP client will communicate. The default is 0 and will
/// cause the UDP client not to bind to a local port.
/// </param>
/// <param name="restrictedToMinimumLevel">
/// The minimum level for events passed through the sink. The default is
/// <see cref="LevelAlias.Minimum"/>.
/// </param>
/// <param name="levelSwitch">
/// A switch allowing the pass-through minimum level to be changed at runtime.
/// </param>
/// <returns>
/// Logger configuration, allowing configuration to continue.
/// </returns>
public static LoggerConfiguration Udp(
this LoggerSinkConfiguration sinkConfiguration,
string remoteAddress,
Expand All @@ -129,20 +197,28 @@ public static LoggerConfiguration Udp(
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
LoggingLevelSwitch levelSwitch = null)
{
return Udp(
sinkConfiguration,
remoteAddress.ToIPAddress(),
remotePort,
formatter,
localPort,
restrictedToMinimumLevel,
levelSwitch);
if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration));

try
{
var client = UdpClientFactory.Create(localPort);
var sink = new UdpSink(client, remoteAddress, remotePort, formatter);

return sinkConfiguration.Sink(sink, restrictedToMinimumLevel, levelSwitch);
}
catch (Exception e)
{
SelfLog.WriteLine("Unable to create UDP sink: {0}", e);
return sinkConfiguration.Sink(new NullSink(), LevelAlias.Maximum, null);
}
}

/// <summary>
/// Adds a sink that sends log events as UDP packages over the network.
/// </summary>
/// <param name="sinkConfiguration">Logger sink configuration.</param>
/// <param name="sinkConfiguration">
/// Logger sink configuration.
/// </param>
/// <param name="remoteAddress">
/// The <see cref="IPAddress"/> of the remote host or multicast group to which the UDP
/// client should sent the logging event.
Expand All @@ -166,7 +242,9 @@ public static LoggerConfiguration Udp(
/// <param name="levelSwitch">
/// A switch allowing the pass-through minimum level to be changed at runtime.
/// </param>
/// <returns>Logger configuration, allowing configuration to continue.</returns>
/// <returns>
/// Logger configuration, allowing configuration to continue.
/// </returns>
public static LoggerConfiguration Udp(
this LoggerSinkConfiguration sinkConfiguration,
IPAddress remoteAddress,
Expand All @@ -176,20 +254,15 @@ public static LoggerConfiguration Udp(
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
LoggingLevelSwitch levelSwitch = null)
{
if (sinkConfiguration == null)
throw new ArgumentNullException(nameof(sinkConfiguration));

try
{
var client = UdpClientFactory.Create(localPort, remoteAddress);
var sink = new UdpSink(client, remoteAddress, remotePort, formatter);
return sinkConfiguration.Sink(sink, restrictedToMinimumLevel, levelSwitch);
}
catch (Exception e)
{
SelfLog.WriteLine("Unable to create UDP sink: {0}", e);
return sinkConfiguration.Sink(new NullSink(), LevelAlias.Maximum, null);
}
return Udp(
sinkConfiguration,
remoteAddress.ToString(),
remotePort,
formatter,
localPort,
restrictedToMinimumLevel,
levelSwitch
);
}
}
}
8 changes: 1 addition & 7 deletions src/Serilog.Sinks.Udp/Serilog.Sinks.Udp.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">

FantasticFiasco marked this conversation as resolved.
Show resolved Hide resolved
<PropertyGroup>
<VersionPrefix>4.1.0</VersionPrefix>
<AssemblyName>Serilog.Sinks.Udp</AssemblyName>
Expand All @@ -21,22 +20,17 @@
<PackageLicenseUrl>http://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl>
<PackageReleaseNotes>For release notes, please see the change log on GitHub.</PackageReleaseNotes>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Serilog.Sinks.PeriodicBatching" Version="2.*" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.3'">
<PackageReference Include="System.Net.NameResolution" Version="4.*" />
</ItemGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net45' ">
<DefineConstants>$(DefineConstants);NET4</DefineConstants>
</PropertyGroup>

</Project>
</Project>
27 changes: 16 additions & 11 deletions src/Serilog.Sinks.Udp/Sinks/Udp/Private/IUdpClient.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
// Copyright 2015-2018 Serilog Contributors
//
//
// 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.

using System.Net;
using System.Threading.Tasks;

namespace Serilog.Sinks.Udp.Private
Expand All @@ -25,17 +24,23 @@ public interface IUdpClient
/// <summary>
/// Sends a UDP datagram asynchronously to a remote host.
/// </summary>
/// <param name="datagram">The datagram.
/// <param name="datagram">
/// An array of type <see cref="byte"/> that specifies the UDP datagram that you intend to
/// send represented as an array of bytes.
/// </param>
/// <param name="bytes">The number of bytes in the datagram.</param>
/// <param name="endPoint">
/// An <see cref="IPEndPoint"/> that represents the host and port to which to send the
/// datagram.
/// <param name="bytes">
/// The number of bytes in the datagram.
/// </param>
/// <returns>Returns <see cref="Task{TResult}"/>.</returns>
Task<int> SendAsync(byte[] datagram, int bytes, IPEndPoint endPoint);
/// <param name="hostname">
/// The name of the remote host to which you intend to send the datagram.
/// </param>
/// <param name="port">
/// The remote port number with which you intend to communicate.
/// </param>
/// <returns>
/// Returns <see cref="Task{TResult}"/>.
/// </returns>
Task<int> SendAsync(byte[] datagram, int bytes, string hostname, int port);

#if NET4
/// <summary>
Expand Down
Loading