我正在一个解决方案中工作,该解决方案在项目中共享的库中具有静态日志记录对象。这是它的结构:
public class AppLog
{
private static string _logFile;
private static string _appName;
public static string AppName
{
get { return _appName; }
set
{
_appName = value;
InitLogFilePath(); // initializes _logFile according to _appName
}
}
public static Write(string msg)
{
// writes to _logFile
}
}
它适用于各种Windows应用程序和Windows服务:它们可以在启动时初始化AppLog.AppName,并且可以在整个代码中调用AppLog.Write
。共享模块写入根据AppName
初始化命名的文件。
我遇到的问题是在WCF Web服务中使用它。 Web服务配置为InstanceContextMode.PerCall
。根据{{1}}初始化AppLog.AppName
。但由于多个Web服务在同一AppDomain中运行,因此共享此静态数据。因此,一个ws会调用ServiceHostBase.Description.Name
集,并且会在下一个调用时更改,这可能会有不同的AppLog.AppName
。
如何对其进行重组,以便在我的解决方案中仍然可以在整个项目中使用ServiceHostBase.Description.Name
,但为每个Web服务处理命名的方式不同?
如果可以判断代码是否在Web服务中运行,并且我可以检索服务的ServiceHostBase.Description,那么我可以维护查找相应的文件名。但我还没有找到办法做到这一点。
答案 0 :(得分:0)
鉴于您的日志记录结构的方式,没有一个好的解决方案。
大多数日志库都是结构化的,以便您创建记录器的实例,将实例传递给任何特定于应用程序的数据(如AppName),然后将该实例存储在私有静态成员中。静态存储位于应用程序中,而不是日志记录库中。这可以避免您拥有的共享冲突,并且仍然只创建少量固定数量的记录器实例。
为了说明这一点,这里是来自log4net的标准CodeProject log4net tutorial示例。此代码将当前类名传递给记录器的实例。
private static readonly log4net.ILog log = log4net.LogManager.GetLogger
(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
我的建议是查看更改为log4net或NuGet上可用的任何其他日志包。
答案 1 :(得分:0)
根据您的情况,AppName不应该在哪里。您需要一个包含AppName的per-webservice日志记录外观,并将核心“Write”逻辑传递给您当前的AppLog。然后,每个Web服务都有自己的LogFacade实例。
class LogFacade
{
public string AppName {get; private set;}
LogFacade(string appName)
{
AppName = appName;
}
public void Write(string msg)
{
AppLog.Write(string.format("[{0}]{1}", AppName, msg));
}
}
或者正如ErnieL所说,看看log4net。