Skip to content

Commit 91f3682

Browse files
Merge pull request #296 from rabbitmq/rabbitmq-dotnet-client-94
Implement logging using an EventSource
2 parents 3fe6446 + 3d093fd commit 91f3682

File tree

10 files changed

+368
-24
lines changed

10 files changed

+368
-24
lines changed

projects/client/RabbitMQ.Client/project.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@
3434
},
3535
"dependencies": {},
3636
"frameworks": {
37-
"net451": {},
37+
"net451": {
38+
"dependencies": {
39+
"Microsoft.Diagnostics.Tracing.EventSource.Redist": "1.1.*"
40+
}
41+
},
3842
"netstandard1.5": {
3943
"buildOptions": {
4044
"define": [
@@ -46,6 +50,7 @@
4650
"System.Collections.Concurrent": "4.0.12",
4751
"System.Console": "4.0.0",
4852
"System.Diagnostics.Debug": "4.0.11",
53+
"System.Diagnostics.Tracing": "4.1.0",
4954
"System.IO": "4.1.0",
5055
"System.Linq": "4.1.0",
5156
"System.Net.NameResolution": "4.0.0",

projects/client/RabbitMQ.Client/src/client/impl/AutorecoveringConnection.cs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ public void BeginAutomaticRecovery()
420420

421421
protected void PerformAutomaticRecovery()
422422
{
423+
ESLog.Info("Performing automatic recovery");
423424
lock (recoveryLockTarget)
424425
{
425426
if (RecoverConnectionDelegate())
@@ -435,8 +436,13 @@ protected void PerformAutomaticRecovery()
435436
RecoverConsumers();
436437
}
437438

439+
ESLog.Info("Connection recovery completed");
438440
RunRecoveryEventHandlers();
439441
}
442+
else
443+
{
444+
ESLog.Warn("Connection delegate was manually closed. Aborted recovery.");
445+
}
440446
}
441447
}
442448

@@ -636,13 +642,7 @@ private void Init(IFrameHandler fh)
636642
}
637643
catch (Exception e)
638644
{
639-
// TODO: logging
640-
#if NETFX_CORE
641-
System.Diagnostics.Debug.WriteLine(
642-
#else
643-
Console.WriteLine(
644-
#endif
645-
"BeginAutomaticRecovery() failed: {0}", e);
645+
ESLog.Error("BeginAutomaticRecovery() failed.", e);
646646
}
647647
}
648648
}
@@ -767,13 +767,7 @@ protected void EnsureIsOpen()
767767

768768
protected void HandleTopologyRecoveryException(TopologyRecoveryException e)
769769
{
770-
// TODO
771-
#if NETFX_CORE
772-
System.Diagnostics.Debug.WriteLine(
773-
#else
774-
Console.WriteLine(
775-
#endif
776-
"Topology recovery exception: {0}", e);
770+
ESLog.Error("Topology recovery exception", e);
777771
}
778772

779773
protected void PropagateQueueNameChangeToBindings(string oldName, string newName)
@@ -842,7 +836,8 @@ protected bool RecoverConnectionDelegate()
842836
}
843837
catch (Exception e)
844838
{
845-
// Trigger recovery error event
839+
ESLog.Error("Connection recovery exception.", e);
840+
// Trigger recovery error events
846841
var handler = m_connectionRecoveryError;
847842
if (handler != null)
848843
{
@@ -861,12 +856,12 @@ protected bool RecoverConnectionDelegate()
861856
}
862857
}
863858
}
859+
864860
#if NETFX_CORE
865861
System.Threading.Tasks.Task.Delay(m_factory.NetworkRecoveryInterval).Wait();
866862
#else
867863
Thread.Sleep(m_factory.NetworkRecoveryInterval);
868864
#endif
869-
// TODO: provide a way to handle these exceptions
870865
}
871866
}
872867

projects/client/RabbitMQ.Client/src/client/impl/Connection.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -563,12 +563,12 @@ public void HandleMainLoopException(ShutdownEventArgs reason)
563563
if (!SetCloseReason(reason))
564564
{
565565
LogCloseError("Unexpected Main Loop Exception while closing: "
566-
+ reason, null);
566+
+ reason, new Exception(reason.ToString()));
567567
return;
568568
}
569569

570570
OnShutdown();
571-
LogCloseError("Unexpected connection closure: " + reason, null);
571+
LogCloseError("Unexpected connection closure: " + reason, new Exception(reason.ToString()));
572572
}
573573

574574
public bool HardProtocolExceptionHandler(HardProtocolException hpe)
@@ -616,6 +616,7 @@ public void InternalClose(ShutdownEventArgs reason)
616616

617617
public void LogCloseError(String error, Exception ex)
618618
{
619+
ESLog.Error(error, ex);
619620
m_shutdownReport.Add(new ShutdownReportEntry(error, ex));
620621
}
621622

@@ -1049,6 +1050,7 @@ public void HeartbeatReadTimerCallback(object state)
10491050
{
10501051
String description = String.Format("Heartbeat missing with heartbeat == {0} seconds", m_heartbeat);
10511052
var eose = new EndOfStreamException(description);
1053+
ESLog.Error(description, eose);
10521054
m_shutdownReport.Add(new ShutdownReportEntry(description, eose));
10531055
HandleMainLoopException(
10541056
new ShutdownEventArgs(ShutdownInitiator.Library, 0, "End of stream", eose));
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// This source code is dual-licensed under the Apache License, version
2+
// 2.0, and the Mozilla Public License, version 1.1.
3+
//
4+
// The APL v2.0:
5+
//
6+
//---------------------------------------------------------------------------
7+
// Copyright (c) 2007-2016 Pivotal Software, Inc.
8+
//
9+
// Licensed under the Apache License, Version 2.0 (the "License");
10+
// you may not use this file except in compliance with the License.
11+
// You may obtain a copy of the License at
12+
//
13+
// http://www.apache.org/licenses/LICENSE-2.0
14+
//
15+
// Unless required by applicable law or agreed to in writing, software
16+
// distributed under the License is distributed on an "AS IS" BASIS,
17+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
// See the License for the specific language governing permissions and
19+
// limitations under the License.
20+
//---------------------------------------------------------------------------
21+
//
22+
// The MPL v1.1:
23+
//
24+
//---------------------------------------------------------------------------
25+
// The contents of this file are subject to the Mozilla Public License
26+
// Version 1.1 (the "License"); you may not use this file except in
27+
// compliance with the License. You may obtain a copy of the License
28+
// at http://www.mozilla.org/MPL/
29+
//
30+
// Software distributed under the License is distributed on an "AS IS"
31+
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
32+
// the License for the specific language governing rights and
33+
// limitations under the License.
34+
//
35+
// The Original Code is RabbitMQ.
36+
//
37+
// The Initial Developer of the Original Code is Pivotal Software, Inc.
38+
// Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved.
39+
//---------------------------------------------------------------------------
40+
41+
namespace RabbitMQ.Client
42+
{
43+
public static class ESLog
44+
{
45+
public static void Info(string message)
46+
{
47+
Logging.RabbitMqClientEventSource.Log.Info(message);
48+
}
49+
50+
public static void Info(string message, params object[] args)
51+
{
52+
var msg = string.Format(message, args);
53+
Info(msg);
54+
}
55+
56+
public static void Warn(string message)
57+
{
58+
Logging.RabbitMqClientEventSource.Log.Warn(message);
59+
}
60+
61+
public static void Warn(string message, params object[] args)
62+
{
63+
var msg = string.Format(message, args);
64+
Warn(msg);
65+
}
66+
67+
public static void Error(string message, System.Exception ex)
68+
{
69+
Logging.RabbitMqClientEventSource.Log.Error(message, ex);
70+
}
71+
72+
public static void Error(string message, System.Exception ex, params object[] args)
73+
{
74+
var msg = string.Format(message, args);
75+
Error(msg, ex);
76+
}
77+
}
78+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// This source code is dual-licensed under the Apache License, version
2+
// 2.0, and the Mozilla Public License, version 1.1.
3+
//
4+
// The APL v2.0:
5+
//
6+
//---------------------------------------------------------------------------
7+
// Copyright (c) 2007-2016 Pivotal Software, Inc.
8+
//
9+
// Licensed under the Apache License, Version 2.0 (the "License");
10+
// you may not use this file except in compliance with the License.
11+
// You may obtain a copy of the License at
12+
//
13+
// http://www.apache.org/licenses/LICENSE-2.0
14+
//
15+
// Unless required by applicable law or agreed to in writing, software
16+
// distributed under the License is distributed on an "AS IS" BASIS,
17+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
// See the License for the specific language governing permissions and
19+
// limitations under the License.
20+
//---------------------------------------------------------------------------
21+
//
22+
// The MPL v1.1:
23+
//
24+
//---------------------------------------------------------------------------
25+
// The contents of this file are subject to the Mozilla Public License
26+
// Version 1.1 (the "License"); you may not use this file except in
27+
// compliance with the License. You may obtain a copy of the License
28+
// at http://www.mozilla.org/MPL/
29+
//
30+
// Software distributed under the License is distributed on an "AS IS"
31+
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
32+
// the License for the specific language governing rights and
33+
// limitations under the License.
34+
//
35+
// The Original Code is RabbitMQ.
36+
//
37+
// The Initial Developer of the Original Code is Pivotal Software, Inc.
38+
// Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved.
39+
//---------------------------------------------------------------------------
40+
41+
namespace RabbitMQ.Client.Logging
42+
{
43+
using System;
44+
#if NET451
45+
using Microsoft.Diagnostics.Tracing;
46+
#else
47+
using System.Diagnostics.Tracing;
48+
#endif
49+
50+
[EventSource(Name="rabbitmq-dotnet-client")]
51+
public sealed class RabbitMqClientEventSource : EventSource
52+
{
53+
public class Keywords
54+
{
55+
public const EventKeywords Log = (EventKeywords)1;
56+
}
57+
58+
public RabbitMqClientEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat)
59+
{
60+
}
61+
62+
public static RabbitMqClientEventSource Log = new RabbitMqClientEventSource ();
63+
64+
[Event(1, Message = "INFO", Keywords = Keywords.Log, Level = EventLevel.Informational)]
65+
public void Info(string message)
66+
{
67+
if(IsEnabled())
68+
this.WriteEvent(1, message);
69+
}
70+
71+
[Event(2, Message = "WARN", Keywords = Keywords.Log, Level = EventLevel.Warning)]
72+
public void Warn(string message)
73+
{
74+
if(IsEnabled())
75+
this.WriteEvent(2, message);
76+
}
77+
78+
[Event(3, Message = "ERROR", Keywords = Keywords.Log, Level = EventLevel.Error)]
79+
public void Error(string message, RabbitMqExceptionDetail ex)
80+
{
81+
if(IsEnabled())
82+
this.WriteEvent(3, message, ex);
83+
}
84+
85+
[NonEvent]
86+
public void Error(string message, Exception ex)
87+
{
88+
Error(message, new RabbitMqExceptionDetail(ex));
89+
}
90+
}
91+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// This source code is dual-licensed under the Apache License, version
2+
// 2.0, and the Mozilla Public License, version 1.1.
3+
//
4+
// The APL v2.0:
5+
//
6+
//---------------------------------------------------------------------------
7+
// Copyright (c) 2007-2016 Pivotal Software, Inc.
8+
//
9+
// Licensed under the Apache License, Version 2.0 (the "License");
10+
// you may not use this file except in compliance with the License.
11+
// You may obtain a copy of the License at
12+
//
13+
// http://www.apache.org/licenses/LICENSE-2.0
14+
//
15+
// Unless required by applicable law or agreed to in writing, software
16+
// distributed under the License is distributed on an "AS IS" BASIS,
17+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
// See the License for the specific language governing permissions and
19+
// limitations under the License.
20+
//---------------------------------------------------------------------------
21+
//
22+
// The MPL v1.1:
23+
//
24+
//---------------------------------------------------------------------------
25+
// The contents of this file are subject to the Mozilla Public License
26+
// Version 1.1 (the "License"); you may not use this file except in
27+
// compliance with the License. You may obtain a copy of the License
28+
// at http://www.mozilla.org/MPL/
29+
//
30+
// Software distributed under the License is distributed on an "AS IS"
31+
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
32+
// the License for the specific language governing rights and
33+
// limitations under the License.
34+
//
35+
// The Original Code is RabbitMQ.
36+
//
37+
// The Initial Developer of the Original Code is Pivotal Software, Inc.
38+
// Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved.
39+
//---------------------------------------------------------------------------
40+
41+
namespace RabbitMQ.Client.Logging
42+
{
43+
using System;
44+
using System.Collections.Generic;
45+
#if NET451
46+
using Microsoft.Diagnostics.Tracing;
47+
#else
48+
using System.Diagnostics.Tracing;
49+
#endif
50+
51+
public sealed class RabbitMqConsoleEventListener : EventListener, IDisposable
52+
{
53+
public RabbitMqConsoleEventListener()
54+
{
55+
this.EnableEvents(RabbitMqClientEventSource.Log, EventLevel.Informational, RabbitMqClientEventSource.Keywords.Log);
56+
}
57+
58+
protected override void OnEventWritten(EventWrittenEventArgs eventData)
59+
{
60+
foreach(var pl in eventData.Payload)
61+
{
62+
var dict = pl as IDictionary<string, object>;
63+
if(dict != null)
64+
{
65+
var rex = new RabbitMqExceptionDetail(dict);
66+
Console.WriteLine("{0}: {1}", eventData.Level, rex.ToString());
67+
}
68+
else
69+
{
70+
Console.WriteLine("{0}: {1}", eventData.Level, pl.ToString());
71+
}
72+
}
73+
}
74+
75+
public override void Dispose()
76+
{
77+
this.DisableEvents(RabbitMqClientEventSource.Log);
78+
}
79+
}
80+
}

0 commit comments

Comments
 (0)