diff --git a/.travis.yml b/.travis.yml
index 602a3f5..da48bb8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,6 +12,6 @@ deploy:
provider: script
skip_cleanup: true
script:
- - cd src/Websocket.Client && dotnet pack /p:PackageVersion=1.0.$TRAVIS_BUILD_NUMBER -c Release && cd bin/Release && dotnet nuget push **/*.1.0.$TRAVIS_BUILD_NUMBER.nupkg -k $NUGET_API_KEY -s https://api.nuget.org/v3/index.json
+ - cd src/Websocket.Client && dotnet pack /p:PackageVersion=2.0.$TRAVIS_BUILD_NUMBER -c Release && cd bin/Release && dotnet nuget push **/*.2.0.$TRAVIS_BUILD_NUMBER.nupkg -k $NUGET_API_KEY -s https://api.nuget.org/v3/index.json
on:
branch: master
\ No newline at end of file
diff --git a/README.md b/README.md
index fdb93a9..7b58bf6 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ This is a wrapper over native C# class `ClientWebSocket` with built-in reconnect
* installation via NuGet ([Websocket.Client](https://www.nuget.org/packages/Websocket.Client))
* targeting .NET Standard 2.0 (.NET Core, Linux/MacOS compatible)
* reactive extensions ([Rx.NET](https://github.com/Reactive-Extensions/Rx.NET))
-* integrated logging ([Serilog](https://serilog.net/))
+* integrated logging abstraction ([LibLog](https://github.com/damianh/LibLog))
### Usage
diff --git a/Websocket.Client.sln.DotSettings b/Websocket.Client.sln.DotSettings
new file mode 100644
index 0000000..c232c2e
--- /dev/null
+++ b/Websocket.Client.sln.DotSettings
@@ -0,0 +1,2 @@
+
+ True
\ No newline at end of file
diff --git a/src/Websocket.Client/IWebsocketClient.cs b/src/Websocket.Client/IWebsocketClient.cs
index 4c7cd03..540579b 100644
--- a/src/Websocket.Client/IWebsocketClient.cs
+++ b/src/Websocket.Client/IWebsocketClient.cs
@@ -35,6 +35,12 @@ public interface IWebsocketClient : IDisposable
///
int ErrorReconnectTimeoutMs { get; set; }
+ ///
+ /// Get or set the name of the current websocket client instance.
+ /// For logging purpose (in case you use more parallel websocket clients and want to distinguish between them)
+ ///
+ string Name { get; set;}
+
///
/// Returns true if Start() method was called at least once. False if not started or disposed
///
diff --git a/src/Websocket.Client/Websocket.Client.csproj b/src/Websocket.Client/Websocket.Client.csproj
index 3313f36..7fd7568 100644
--- a/src/Websocket.Client/Websocket.Client.csproj
+++ b/src/Websocket.Client/Websocket.Client.csproj
@@ -3,11 +3,11 @@
netstandard2.0
Websocket.Client
- 1.0.0
+ 2.0.0
Mariusz Kotas
Client for websocket API with built-in reconnection and error handling
false
- Initial release
+ Release of version 2.0
Copyright 2018 Mariusz Kotas. All rights reserved.
websockets websocket client
https://github.com/Marfusios/Websocket.Client/blob/master/LICENSE
@@ -17,12 +17,15 @@
Git
true
true
- 1.0.0.0
- 1.0.0.0
+ 2.0.0.0
+ 2.0.0.0
-
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
diff --git a/src/Websocket.Client/WebsocketClient.cs b/src/Websocket.Client/WebsocketClient.cs
index aecf2a5..3854e2a 100644
--- a/src/Websocket.Client/WebsocketClient.cs
+++ b/src/Websocket.Client/WebsocketClient.cs
@@ -6,7 +6,7 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using Serilog;
+using Websocket.Client.Logging;
namespace Websocket.Client
{
@@ -15,6 +15,8 @@ namespace Websocket.Client
///
public class WebsocketClient : IWebsocketClient
{
+ private static readonly ILog Logger = LogProvider.GetCurrentClassLogger();
+
private readonly Uri _url;
private Timer _lastChanceTimer;
private readonly Func _clientFactory;
@@ -23,8 +25,8 @@ public class WebsocketClient : IWebsocketClient
private bool _disposing = false;
private ClientWebSocket _client;
- private CancellationTokenSource _cancelation;
- private CancellationTokenSource _cancelationTotal;
+ private CancellationTokenSource _cancellation;
+ private CancellationTokenSource _cancellationTotal;
private readonly Subject _messageReceivedSubject = new Subject();
private readonly Subject _reconnectionSubject = new Subject();
@@ -50,12 +52,12 @@ public WebsocketClient(Uri url, Func clientFactory = null)
public IObservable MessageReceived => _messageReceivedSubject.AsObservable();
///
- /// Stream for reconnection event (trigerred after the new connection)
+ /// Stream for reconnection event (triggered after the new connection)
///
public IObservable ReconnectionHappened => _reconnectionSubject.AsObservable();
///
- /// Stream for disconnection event (trigerred after the connection was lost)
+ /// Stream for disconnection event (triggered after the connection was lost)
///
public IObservable DisconnectionHappened => _disconnectedSubject.AsObservable();
@@ -71,6 +73,12 @@ public WebsocketClient(Uri url, Func clientFactory = null)
///
public int ErrorReconnectTimeoutMs { get; set; } = 60 * 1000;
+ ///
+ /// Get or set the name of the current websocket client instance.
+ /// For logging purpose (in case you use more parallel websocket clients and want to distinguish between them)
+ ///
+ public string Name { get; set;}
+
///
/// Returns true if Start() method was called at least once. False if not started or disposed
///
@@ -87,21 +95,21 @@ public WebsocketClient(Uri url, Func clientFactory = null)
public void Dispose()
{
_disposing = true;
- Log.Debug(L("Disposing.."));
+ Logger.Debug(L("Disposing.."));
try
{
_lastChanceTimer?.Dispose();
- _cancelation?.Cancel();
- _cancelationTotal?.Cancel();
+ _cancellation?.Cancel();
+ _cancellationTotal?.Cancel();
_client?.Abort();
_client?.Dispose();
- _cancelation?.Dispose();
- _cancelationTotal?.Dispose();
+ _cancellation?.Dispose();
+ _cancellationTotal?.Dispose();
_messagesToSendQueue?.Dispose();
}
catch (Exception e)
{
- Log.Error(e, L($"Failed to dispose client, error: {e.Message}"));
+ Logger.Error(e, L($"Failed to dispose client, error: {e.Message}"));
}
IsStarted = false;
@@ -115,16 +123,16 @@ public async Task Start()
{
if (IsStarted)
{
- Log.Debug(L("Client already started, ignoring.."));
+ Logger.Debug(L("Client already started, ignoring.."));
return;
}
IsStarted = true;
- Log.Debug(L("Starting.."));
- _cancelation = new CancellationTokenSource();
- _cancelationTotal = new CancellationTokenSource();
+ Logger.Debug(L("Starting.."));
+ _cancellation = new CancellationTokenSource();
+ _cancellationTotal = new CancellationTokenSource();
- await StartClient(_url, _cancelation.Token, ReconnectionType.Initial).ConfigureAwait(false);
+ await StartClient(_url, _cancellation.Token, ReconnectionType.Initial).ConfigureAwait(false);
StartBackgroundThreadForSending();
}
@@ -164,7 +172,7 @@ public async Task Reconnect()
{
if (!IsStarted)
{
- Log.Debug(L("Client not started, ignoring reconnection.."));
+ Logger.Debug(L("Client not started, ignoring reconnection.."));
return;
}
await Reconnect(ReconnectionType.ByUser).ConfigureAwait(false);
@@ -174,7 +182,7 @@ private async Task SendFromQueue()
{
try
{
- foreach (var message in _messagesToSendQueue.GetConsumingEnumerable(_cancelationTotal.Token))
+ foreach (var message in _messagesToSendQueue.GetConsumingEnumerable(_cancellationTotal.Token))
{
try
{
@@ -182,7 +190,7 @@ private async Task SendFromQueue()
}
catch (Exception e)
{
- Log.Error(L($"Failed to send message: '{message}'. Error: {e.Message}"));
+ Logger.Error(L($"Failed to send message: '{message}'. Error: {e.Message}"));
}
}
}
@@ -192,7 +200,7 @@ private async Task SendFromQueue()
}
catch (Exception e)
{
- if (_cancelationTotal.IsCancellationRequested || _disposing)
+ if (_cancellationTotal.IsCancellationRequested || _disposing)
{
// disposing/canceling, do nothing and exit
return;
@@ -206,22 +214,22 @@ private async Task SendFromQueue()
private void StartBackgroundThreadForSending()
{
#pragma warning disable 4014
- Task.Factory.StartNew(_ => SendFromQueue(), TaskCreationOptions.LongRunning, _cancelationTotal.Token);
+ Task.Factory.StartNew(_ => SendFromQueue(), TaskCreationOptions.LongRunning, _cancellationTotal.Token);
#pragma warning restore 4014
}
private async Task SendInternal(string message)
{
- Log.Verbose(L($"Sending: {message}"));
+ Logger.Trace(L($"Sending: {message}"));
var buffer = Encoding.UTF8.GetBytes(message);
var messageSegment = new ArraySegment(buffer);
var client = await GetClient().ConfigureAwait(false);
- await client.SendAsync(messageSegment, WebSocketMessageType.Text, true, _cancelation.Token).ConfigureAwait(false);
+ await client.SendAsync(messageSegment, WebSocketMessageType.Text, true, _cancellation.Token).ConfigureAwait(false);
}
private async Task StartClient(Uri uri, CancellationToken token, ReconnectionType type)
{
- DeactiveLastChance();
+ DeactivateLastChance();
_client = _clientFactory();
try
@@ -237,7 +245,7 @@ private async Task StartClient(Uri uri, CancellationToken token, ReconnectionTyp
catch (Exception e)
{
_disconnectedSubject.OnNext(DisconnectionType.Error);
- Log.Error(e, L("Exception while connecting. " +
+ Logger.Error(e, L("Exception while connecting. " +
$"Waiting {ErrorReconnectTimeoutMs/1000} sec before next reconnection try."));
await Task.Delay(ErrorReconnectTimeoutMs, token).ConfigureAwait(false);
await Reconnect(ReconnectionType.Error).ConfigureAwait(false);
@@ -261,12 +269,12 @@ private async Task Reconnect(ReconnectionType type)
if(type != ReconnectionType.Error)
_disconnectedSubject.OnNext(TranslateTypeToDisconnection(type));
- Log.Debug(L("Reconnecting..."));
- _cancelation.Cancel();
+ Logger.Debug(L("Reconnecting..."));
+ _cancellation.Cancel();
await Task.Delay(1000).ConfigureAwait(false);
- _cancelation = new CancellationTokenSource();
- await StartClient(_url, _cancelation.Token, type).ConfigureAwait(false);
+ _cancellation = new CancellationTokenSource();
+ await StartClient(_url, _cancellation.Token, type).ConfigureAwait(false);
}
private async Task Listen(ClientWebSocket client, CancellationToken token)
@@ -290,7 +298,7 @@ private async Task Listen(ClientWebSocket client, CancellationToken token)
} while (!result.EndOfMessage);
var received = resultMessage.ToString();
- Log.Verbose(L($"Received: {received}"));
+ Logger.Trace(L($"Received: {received}"));
_lastReceivedMsg = DateTime.UtcNow;
_messageReceivedSubject.OnNext(received);
@@ -302,7 +310,7 @@ private async Task Listen(ClientWebSocket client, CancellationToken token)
}
catch (Exception e)
{
- Log.Error(e, L("Error while listening to websocket stream"));
+ Logger.Error(e, L("Error while listening to websocket stream"));
}
}
@@ -312,7 +320,7 @@ private void ActivateLastChance()
_lastChanceTimer = new Timer(LastChance, null, timerMs, timerMs);
}
- private void DeactiveLastChance()
+ private void DeactivateLastChance()
{
_lastChanceTimer?.Dispose();
_lastChanceTimer = null;
@@ -324,9 +332,9 @@ private void LastChance(object state)
var diffMs = Math.Abs(DateTime.UtcNow.Subtract(_lastReceivedMsg).TotalMilliseconds);
if (diffMs > timeoutMs)
{
- Log.Debug(L($"Last message received more than {timeoutMs:F} ms ago. Hard restart.."));
+ Logger.Debug(L($"Last message received more than {timeoutMs:F} ms ago. Hard restart.."));
- DeactiveLastChance();
+ DeactivateLastChance();
_client?.Abort();
_client?.Dispose();
#pragma warning disable 4014
@@ -337,12 +345,13 @@ private void LastChance(object state)
private string L(string msg)
{
- return $"[WEBSOCKET CLIENT] {msg}";
+ var name = Name ?? "CLIENT";
+ return $"[WEBSOCKET {name}] {msg}";
}
private DisconnectionType TranslateTypeToDisconnection(ReconnectionType type)
{
- // beaware enum indexes must correspond to each other
+ // beware enum indexes must correspond to each other
return (DisconnectionType) type;
}
}
diff --git a/test_integration/Websocket.Client.Sample.NetFramework/Program.cs b/test_integration/Websocket.Client.Sample.NetFramework/Program.cs
index 3c34ce6..a308110 100644
--- a/test_integration/Websocket.Client.Sample.NetFramework/Program.cs
+++ b/test_integration/Websocket.Client.Sample.NetFramework/Program.cs
@@ -1,7 +1,6 @@
using System;
using System.IO;
using System.Reflection;
-using System.Runtime.Loader;
using System.Threading;
using System.Threading.Tasks;
using Serilog;
@@ -18,7 +17,6 @@ static void Main(string[] args)
InitLogging();
AppDomain.CurrentDomain.ProcessExit += CurrentDomainOnProcessExit;
- AssemblyLoadContext.Default.Unloading += DefaultOnUnloading;
Console.CancelKeyPress += ConsoleOnCancelKeyPress;
Console.WriteLine("|=======================|");
@@ -35,9 +33,14 @@ static void Main(string[] args)
var url = new Uri("wss://www.bitmex.com/realtime");
using (var client = new WebsocketClient(url))
{
+ client.Name = "Bitmex";
client.ReconnectTimeoutMs = (int)TimeSpan.FromSeconds(30).TotalMilliseconds;
client.ReconnectionHappened.Subscribe(type =>
Log.Information($"Reconnection happened, type: {type}"));
+ client.DisconnectionHappened.Subscribe(type =>
+ Log.Warning($"Disconnection happened, type: {type}"));
+
+ client.MessageReceived.Subscribe(msg => Log.Information($"Message received: {msg}"));
client.Start();
@@ -78,12 +81,6 @@ private static void CurrentDomainOnProcessExit(object sender, EventArgs eventArg
ExitEvent.Set();
}
- private static void DefaultOnUnloading(AssemblyLoadContext assemblyLoadContext)
- {
- Log.Warning("Unloading process");
- ExitEvent.Set();
- }
-
private static void ConsoleOnCancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
Log.Warning("Canceling process");
diff --git a/test_integration/Websocket.Client.Sample.NetFramework/Websocket.Client.Sample.NetFramework.csproj b/test_integration/Websocket.Client.Sample.NetFramework/Websocket.Client.Sample.NetFramework.csproj
index cc941a5..0af8357 100644
--- a/test_integration/Websocket.Client.Sample.NetFramework/Websocket.Client.Sample.NetFramework.csproj
+++ b/test_integration/Websocket.Client.Sample.NetFramework/Websocket.Client.Sample.NetFramework.csproj
@@ -6,8 +6,8 @@
AnyCPU
{56642A4E-B8CE-4399-9879-3E89C7C1FA3D}
Exe
- Bitmex.Client.Websocket.Sample.NetFramework
- Bitmex.Client.Websocket.Sample.NetFramework
+ Websocket.Client.Sample.NetFramework
+ Websocket.Client.Sample.NetFramework
v4.7.1
512
true
@@ -36,7 +36,7 @@
..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll
- ..\..\packages\Serilog.2.5.0\lib\net46\Serilog.dll
+ ..\..\packages\Serilog.2.8.0\lib\net46\Serilog.dll
..\..\packages\Serilog.Sinks.ColoredConsole.3.0.1\lib\net45\Serilog.Sinks.ColoredConsole.dll
diff --git a/test_integration/Websocket.Client.Sample.NetFramework/packages.config b/test_integration/Websocket.Client.Sample.NetFramework/packages.config
index 9a7f2f7..b03bb6b 100644
--- a/test_integration/Websocket.Client.Sample.NetFramework/packages.config
+++ b/test_integration/Websocket.Client.Sample.NetFramework/packages.config
@@ -1,7 +1,7 @@
-
+
diff --git a/test_integration/Websocket.Client.Sample/Program.cs b/test_integration/Websocket.Client.Sample/Program.cs
index de6c311..6965cda 100644
--- a/test_integration/Websocket.Client.Sample/Program.cs
+++ b/test_integration/Websocket.Client.Sample/Program.cs
@@ -7,6 +7,7 @@
using Serilog;
using Serilog.Events;
+
namespace Websocket.Client.Sample
{
class Program
@@ -35,6 +36,7 @@ static void Main(string[] args)
var url = new Uri("wss://www.bitmex.com/realtime");
using (var client = new WebsocketClient(url))
{
+ client.Name = "Bitmex";
client.ReconnectTimeoutMs = (int)TimeSpan.FromSeconds(30).TotalMilliseconds;
client.ReconnectionHappened.Subscribe(type =>
Log.Information($"Reconnection happened, type: {type}"));
@@ -72,7 +74,8 @@ private static void InitLogging()
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.WriteTo.File(logPath, rollingInterval: RollingInterval.Day)
- .WriteTo.ColoredConsole(LogEventLevel.Verbose)
+ .WriteTo.ColoredConsole(LogEventLevel.Verbose,
+ outputTemplate: "{Timestamp:HH:mm:ss} [{Level:u3}] {Message} {Properties}{NewLine}{Exception}")
.CreateLogger();
}