在log4net中有2个非常好的功能:
Log.Error("Message", myException);
和
Log.ErrorFormat("Message {0}", CustomerId);
产生日志记录在输出日志文件中非常好。例外情况很好,因为它可以很好地打印堆栈跟踪和所有异常细节,而Format 1很好,因为它允许我指定导致失败的参数。是否存在“两全其美”的方法,或某种方式来实现它?
Log.ErrorFormatEx("Message {0}", CustomerId, myException)
编辑:我经历了可能的重复问题,但是它们格式错误,并且没有完全像这样问...我正在寻找扩展方法或现有方法
答案 0 :(得分:5)
您可以创建一个扩展方法:
namespace log4net.Core
{
public class Log4NetExtensions
{
public static void ErrorFormatEx(this ILog logger, string format, Exception exception, params object[] args)
{
logger.Error(string.Format(format, args), exception);
}
}
}
然后您可以像使用任何其他Log4Net
方法一样使用它:
Log.ErrorFormatEx("Message {0}", exception, CustomerId);
答案 1 :(得分:3)
现在用字符串插值解决了这个问题:
Log.Error($"Message {CustomerId}", myException);
答案 2 :(得分:2)
知道这已经得到了解答,但仅适用于可能会发现此替代方案有用的其他用户。我创建了一个ILog接口和一个日志类来集中"我的log4net方法和逻辑。我还为"错误"创建了多个重载。方法
<强> ILog.cs 强>
public interface ILog
{
void Error(Exception exception);
void Error(string customMessage, Exception exception);
void Error(string format, Exception exception, params object[] args);
void Warn(Exception exception);
void Info(string message);
}
<强> Log.cs 强>
public class Log : ILog
{
public void Error(Exception exception)
{
log4net.ILog logger = log4net.LogManager.GetLogger(exception.TargetSite.DeclaringType);
logger.Error(exception.GetBaseException().Message, exception);
}
public void Error(string customMessage, Exception exception)
{
log4net.ILog logger = log4net.LogManager.GetLogger(exception.TargetSite.DeclaringType);
logger.Error(customMessage, exception);
}
public void Error(string format, Exception exception, params object[] args)
{
log4net.ILog logger = log4net.LogManager.GetLogger(exception.TargetSite.DeclaringType);
logger.Error(string.Format(format, args), exception);
}
public void Warn(Exception exception)
{
log4net.ILog logger = log4net.LogManager.GetLogger(exception.TargetSite.DeclaringType);
logger.Warn(exception.GetBaseException().Message, exception);
}
public void Info(string message)
{
log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
logger.Info(message);
}
}
使用示例
public MyClass DeserializeJsonFile(string path)
{
try
{
using (StreamReader r = new StreamReader(path))
{
string json = r.ReadToEnd();
return JsonConvert.DeserializeObject<MyClass>(json);
}
}
catch (Exception ex)
{
this.log.Error("Error deserializing jsonfile. FilePath: {0}", ex, path);
return null;
}
}
答案 3 :(得分:0)
最简单的方法是使用:
Log.Error($"Message {CustomerId}, {myException}");
答案 4 :(得分:0)
就我而言,我需要临时使用两个记录器(Log4Net 和 Serilog)。我没有写出很好的代码,因为解决方案是暂时的。下面是我用的。
public void Error(Exception exception, string messageTemplate, params object[] propertyValues)
{
_messageTemplateProcessor.Process(messageTemplate, propertyValues, out var parsedMessage);
Log.Error(parsedMessage, exception); //Log4Net
_logger.Error(exception, messageTemplate, propertyValues); //Serilog
}
using System.Collections.Generic;
namespace CommonServices
{
class MessageTemplateProcessor
{
public void Process(string messageTemplate, object[] messageTemplateParameters, out string parsedMessage)
{
var blocks = Parse(messageTemplate);
parsedMessage = string.Empty;
var i = 0;
foreach (var block in blocks)
{
if (!block.IsProperty)
{
parsedMessage += block.Text;
continue;
}
parsedMessage += messageTemplateParameters[i];
i++;
}
}
private IEnumerable<Block> Parse(string messageTemplate)
{
var blocks = new List<Block>();
if (string.IsNullOrEmpty(messageTemplate))
{
return blocks;
}
var stack = new Stack<char>();
var word = string.Empty;
foreach (var ch in messageTemplate)
{
if (ch == '{' && stack.Count == 0)
{
if (!string.IsNullOrEmpty(word))
{
blocks.Add(new Block(word, false));
word = string.Empty;
}
stack.Push(ch);
word += ch;
continue;
}
word += ch;
if ((ch != '{' && ch != '}') || (ch == '}' && stack.Count == 0))
{
continue;
}
if (ch == '{' && stack.Count > 0)
{
stack.Push(ch);
continue;
}
if (ch == '}' && stack.Count > 0)
{
if (stack.Count == 1)
{
blocks.Add(new Block(word, true));
word = string.Empty;
stack.Pop();
continue;
}
if (stack.Peek() == '{')
{
stack.Pop();
}
else
{
stack.Push(ch);
}
}
}
if (!string.IsNullOrEmpty(word))
{
blocks.Add(new Block(word, false));
}
return blocks;
}
class Block
{
public Block(string text, bool isProperty)
{
Text = text;
IsProperty = isProperty;
}
public string Text { get; }
public bool IsProperty { get; }
}
}
}