Skip to content

Commit e9cdbaf

Browse files
committed
Better (and universal) logging (DNET-782).
1 parent 9d440ac commit e9cdbaf

File tree

7 files changed

+249
-46
lines changed

7 files changed

+249
-46
lines changed

Provider/src/FirebirdSql.Data.FirebirdClient/FirebirdClient/FbCommand.cs

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@
2525
using System.Diagnostics;
2626

2727
using FirebirdSql.Data.Common;
28+
using FirebirdSql.Data.Logging;
2829

2930
namespace FirebirdSql.Data.FirebirdClient
3031
{
3132
public sealed class FbCommand : DbCommand, ICloneable
3233
{
34+
static readonly IFbLogger Log = FbLogManager.CreateLogger(nameof(FbCommand));
35+
3336
#region Fields
3437

3538
private CommandType _commandType;
@@ -463,10 +466,7 @@ public override int ExecuteNonQuery()
463466
return RecordsAffected;
464467
}
465468

466-
public new FbDataReader ExecuteReader()
467-
{
468-
return ExecuteReader(CommandBehavior.Default);
469-
}
469+
public new FbDataReader ExecuteReader() => ExecuteReader(CommandBehavior.Default);
470470
public new FbDataReader ExecuteReader(CommandBehavior behavior)
471471
{
472472
CheckCommand();
@@ -1002,8 +1002,6 @@ private void UpdateParameterValues()
10021002

10031003
private void Prepare(bool returnsSet)
10041004
{
1005-
LogCommand();
1006-
10071005
var innerConn = _connection.InnerConnection;
10081006

10091007
// Check if we have a valid transaction
@@ -1071,14 +1069,11 @@ private void Prepare(bool returnsSet)
10711069
}
10721070
}
10731071

1074-
private void ExecuteCommand(CommandBehavior behavior)
1075-
{
1076-
ExecuteCommand(behavior, false);
1077-
}
1078-
1072+
private void ExecuteCommand(CommandBehavior behavior) => ExecuteCommand(behavior, false);
10791073
private void ExecuteCommand(CommandBehavior behavior, bool returnsSet)
10801074
{
1081-
// Prepare statement
1075+
LogCommandExecutionIfEnabled();
1076+
10821077
Prepare(returnsSet);
10831078

10841079
if ((behavior & CommandBehavior.SequentialAccess) == CommandBehavior.SequentialAccess ||
@@ -1257,27 +1252,29 @@ private void CheckCommand()
12571252
}
12581253
}
12591254

1260-
[Conditional(TraceHelper.ConditionalSymbol)]
1261-
private void LogCommand()
1255+
private void LogCommandExecutionIfEnabled()
12621256
{
1263-
if (TraceHelper.HasListeners)
1257+
if (Log.IsEnabled(FbLogLevel.Debug))
12641258
{
1265-
var message = new StringBuilder();
1266-
message.AppendLine("Command:");
1267-
message.AppendLine(_commandText);
1268-
message.AppendLine("Parameters:");
1269-
if (_parameters != null)
1259+
var sb = new StringBuilder();
1260+
sb.AppendLine("Executing command:");
1261+
sb.AppendLine(_commandText);
1262+
if (FbLogManager.IsParameterLoggingEnabled)
12701263
{
1271-
foreach (FbParameter item in _parameters)
1264+
sb.AppendLine("Parameters:");
1265+
if (_parameters?.Count > 0)
12721266
{
1273-
message.AppendLine(string.Format("Name:{0}\tType:{1}\tUsed Value:{2}", item.ParameterName, item.FbDbType, (!IsNullParameterValue(item.InternalValue) ? item.InternalValue : "<null>")));
1267+
foreach (FbParameter item in _parameters)
1268+
{
1269+
sb.AppendLine(string.Format("Name:{0}\tType:{1}\tUsed Value:{2}", item.ParameterName, item.FbDbType, (!IsNullParameterValue(item.InternalValue) ? item.InternalValue : "<null>")));
1270+
}
1271+
}
1272+
else
1273+
{
1274+
sb.AppendLine("<no parameters>");
12741275
}
12751276
}
1276-
else
1277-
{
1278-
message.AppendLine("<no parameters>");
1279-
}
1280-
TraceHelper.Trace(TraceEventType.Information, message.ToString());
1277+
Log.Debug(sb.ToString());
12811278
}
12821279
}
12831280

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* The contents of this file are subject to the Initial
3+
* Developer's Public License Version 1.0 (the "License");
4+
* you may not use this file except in compliance with the
5+
* License. You may obtain a copy of the License at
6+
* https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt.
7+
*
8+
* Software distributed under the License is distributed on
9+
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
10+
* express or implied. See the License for the specific
11+
* language governing rights and limitations under the License.
12+
*
13+
* All Rights Reserved.
14+
*/
15+
16+
//$Authors = Jiri Cincura (jiri@cincura.net)
17+
18+
using System;
19+
using System.Text;
20+
21+
namespace FirebirdSql.Data.Logging
22+
{
23+
public class ConsoleLoggerProvider : IFbLoggingProvider
24+
{
25+
readonly FbLogLevel _minimumLevel;
26+
27+
public ConsoleLoggerProvider(FbLogLevel minimumLevel = FbLogLevel.Info)
28+
{
29+
_minimumLevel = minimumLevel;
30+
}
31+
32+
public IFbLogger CreateLogger(string name) => new ConsoleLogger(_minimumLevel);
33+
34+
sealed class ConsoleLogger : IFbLogger
35+
{
36+
readonly FbLogLevel _minimumLevel;
37+
38+
public ConsoleLogger(FbLogLevel minimumLevel)
39+
{
40+
_minimumLevel = minimumLevel;
41+
}
42+
43+
public bool IsEnabled(FbLogLevel level)
44+
{
45+
return level >= _minimumLevel;
46+
}
47+
48+
public void Log(FbLogLevel level, string msg, Exception exception = null)
49+
{
50+
if (!IsEnabled(level))
51+
return;
52+
53+
var sb = new StringBuilder();
54+
sb.Append("[");
55+
sb.Append(level.ToString().ToUpper());
56+
sb.Append("]");
57+
58+
sb.AppendLine(msg);
59+
60+
if (exception != null)
61+
sb.AppendLine(exception.ToString());
62+
63+
Console.Error.Write(sb.ToString());
64+
}
65+
}
66+
}
67+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* The contents of this file are subject to the Initial
3+
* Developer's Public License Version 1.0 (the "License");
4+
* you may not use this file except in compliance with the
5+
* License. You may obtain a copy of the License at
6+
* https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt.
7+
*
8+
* Software distributed under the License is distributed on
9+
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
10+
* express or implied. See the License for the specific
11+
* language governing rights and limitations under the License.
12+
*
13+
* All Rights Reserved.
14+
*/
15+
16+
//$Authors = Jiri Cincura (jiri@cincura.net)
17+
18+
namespace FirebirdSql.Data.Logging
19+
{
20+
public enum FbLogLevel
21+
{
22+
Trace = 1,
23+
Debug = 2,
24+
Info = 3,
25+
Warn = 4,
26+
Error = 5,
27+
Fatal = 6,
28+
}
29+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* The contents of this file are subject to the Initial
3+
* Developer's Public License Version 1.0 (the "License");
4+
* you may not use this file except in compliance with the
5+
* License. You may obtain a copy of the License at
6+
* https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt.
7+
*
8+
* Software distributed under the License is distributed on
9+
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
10+
* express or implied. See the License for the specific
11+
* language governing rights and limitations under the License.
12+
*
13+
* All Rights Reserved.
14+
*/
15+
16+
//$Authors = Jiri Cincura (jiri@cincura.net)
17+
18+
using System;
19+
20+
namespace FirebirdSql.Data.Logging
21+
{
22+
public static class FbLogManager
23+
{
24+
public static IFbLoggingProvider Provider
25+
{
26+
get
27+
{
28+
_providerRetrieved = true;
29+
return _provider;
30+
}
31+
set
32+
{
33+
if (_providerRetrieved)
34+
throw new InvalidOperationException("The logging provider must be set before any action is taken");
35+
36+
_provider = value ?? throw new ArgumentNullException(nameof(value));
37+
}
38+
}
39+
40+
public static bool IsParameterLoggingEnabled { get; set; }
41+
42+
static IFbLoggingProvider _provider;
43+
static bool _providerRetrieved;
44+
45+
static FbLogManager()
46+
{
47+
_provider = new NullLoggingProvider();
48+
}
49+
50+
internal static IFbLogger CreateLogger(string name) => Provider.CreateLogger("FirebirdClient." + name);
51+
}
52+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* The contents of this file are subject to the Initial
3+
* Developer's Public License Version 1.0 (the "License");
4+
* you may not use this file except in compliance with the
5+
* License. You may obtain a copy of the License at
6+
* https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt.
7+
*
8+
* Software distributed under the License is distributed on
9+
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
10+
* express or implied. See the License for the specific
11+
* language governing rights and limitations under the License.
12+
*
13+
* All Rights Reserved.
14+
*/
15+
16+
//$Authors = Jiri Cincura (jiri@cincura.net)
17+
18+
using System;
19+
20+
namespace FirebirdSql.Data.Logging
21+
{
22+
public interface IFbLogger
23+
{
24+
bool IsEnabled(FbLogLevel level);
25+
void Log(FbLogLevel level, string msg, Exception exception = null);
26+
}
27+
28+
public static class IFbLoggerExtensions
29+
{
30+
public static void Trace(this IFbLogger logger, string msg) => logger.Log(FbLogLevel.Trace, msg);
31+
public static void Debug(this IFbLogger logger, string msg) => logger.Log(FbLogLevel.Debug, msg);
32+
public static void Info(this IFbLogger logger, string msg) => logger.Log(FbLogLevel.Info, msg);
33+
public static void Warn(this IFbLogger logger, string msg) => logger.Log(FbLogLevel.Warn, msg);
34+
public static void Error(this IFbLogger logger, string msg) => logger.Log(FbLogLevel.Error, msg);
35+
public static void Fatal(this IFbLogger logger, string msg) => logger.Log(FbLogLevel.Fatal, msg);
36+
37+
public static void Trace(this IFbLogger logger, string msg, Exception ex) => logger.Log(FbLogLevel.Trace, msg, ex);
38+
public static void Debug(this IFbLogger logger, string msg, Exception ex) => logger.Log(FbLogLevel.Debug, msg, ex);
39+
public static void Info(this IFbLogger logger, string msg, Exception ex) => logger.Log(FbLogLevel.Info, msg, ex);
40+
public static void Warn(this IFbLogger logger, string msg, Exception ex) => logger.Log(FbLogLevel.Warn, msg, ex);
41+
public static void Error(this IFbLogger logger, string msg, Exception ex) => logger.Log(FbLogLevel.Error, msg, ex);
42+
public static void Fatal(this IFbLogger logger, string msg, Exception ex) => logger.Log(FbLogLevel.Fatal, msg, ex);
43+
}
44+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* The contents of this file are subject to the Initial
3+
* Developer's Public License Version 1.0 (the "License");
4+
* you may not use this file except in compliance with the
5+
* License. You may obtain a copy of the License at
6+
* https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt.
7+
*
8+
* Software distributed under the License is distributed on
9+
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
10+
* express or implied. See the License for the specific
11+
* language governing rights and limitations under the License.
12+
*
13+
* All Rights Reserved.
14+
*/
15+
16+
//$Authors = Jiri Cincura (jiri@cincura.net)
17+
18+
namespace FirebirdSql.Data.Logging
19+
{
20+
public interface IFbLoggingProvider
21+
{
22+
IFbLogger CreateLogger(string name);
23+
}
24+
}

Provider/src/FirebirdSql.Data.FirebirdClient/Common/TraceHelper.cs renamed to Provider/src/FirebirdSql.Data.FirebirdClient/Logging/NullLoggingProvider.cs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,22 @@
1616
//$Authors = Jiri Cincura (jiri@cincura.net)
1717

1818
using System;
19-
using System.Diagnostics;
20-
using System.Linq;
2119

22-
namespace FirebirdSql.Data.Common
20+
namespace FirebirdSql.Data.Logging
2321
{
24-
internal static class TraceHelper
22+
sealed class NullLoggingProvider : IFbLoggingProvider
2523
{
26-
public const string Name = "FirebirdSql.Data.FirebirdClient";
27-
public const string ConditionalSymbol = "TRACE";
24+
public IFbLogger CreateLogger(string name) => NullLogger.Instance;
2825

29-
static TraceSource _instance;
30-
31-
static TraceHelper()
26+
sealed class NullLogger : IFbLogger
3227
{
33-
_instance = new TraceSource(Name, SourceLevels.All);
34-
}
28+
internal static NullLogger Instance = new NullLogger();
3529

36-
public static void Trace(TraceEventType eventType, string message)
37-
{
38-
_instance.TraceEvent(eventType, default, message);
39-
_instance.Flush();
40-
}
30+
NullLogger() { }
4131

42-
public static bool HasListeners
43-
{
44-
get { return _instance.Listeners.Count > 0; }
32+
public bool IsEnabled(FbLogLevel level) => false;
33+
34+
public void Log(FbLogLevel level, string msg, Exception exception = null) { }
4535
}
4636
}
4737
}

0 commit comments

Comments
 (0)