Silverlight 应用程序的最佳日志记录模式






4.86/5 (7投票s)
使用 NLog 2.0 对 Silverlight 应用程序进行服务器端日志记录
引言
在这里,我将演示使用 NLog 2.0 对 Silverlight 应用程序进行服务器端日志记录机制。使用此机制,您可以将所有日志集中到一个地方,可以是日志文件、数据库、ftp 等。
为什么要使用 NLog
目前有两种流行的日志记录平台:NLog 和 Log4Net。NLog 2.0 版本专注于为新平台(Silverlight、.NET Framework 4、Windows Phone 7.x)添加支持,改进日志记录架构和可管理性,并解决最常报告的用户问题。它完全支持异步操作。因此,对于 Silverlight,NLog 是最佳选择。
我们可以考虑两种永久日志记录选项:客户端或服务器端。客户端日志记录会影响性能,并且不允许您在集中位置查看日志。现在问题来了,如何使用 NLog 以高效的方式实现服务器端日志记录。
背景
为了实现此应用程序,我将使用以下技术:
- 客户端层使用 Silverlight5
- WCF 服务 - HTTP 绑定(如果需要用于数据库交互,则可选)
- WCF RIA 服务 V1.0 SP2
- NLog 2.0(可从 http://nlog.codeplex.com/ 安装)
Silverlight 业务应用程序
创建一个新的 Silverlight 业务应用程序。将其命名为“BusinessAppMVVM”。
Web 项目
我将向 Web 项目添加 NLog.Config 文件。
将以下代码复制/粘贴到 NLog.Config。我不会深入探讨 config 的不同部分。详细信息可在 NLog 文档中找到。
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <!-- make sure to set 'Copy To Output Directory' option for this file --> <!-- go to http://nlog-project.org/wiki/Configuration_file for more information --> <targets> <!-- Log in a separate thread, possibly queueing up to 5000 messages. When the queue overflows, discard any extra messages--> <target name="file" xsi:type="AsyncWrapper" queueLimit="5000" overflowAction="Discard"> <target xsi:type="File" fileName="${basedir}/logs/${level}.txt" layout="${longdate} ${logger} ${message}" archiveFileName="${basedir}/logs/archives/${level}.{#####}.txt" archiveAboveSize="10240" archiveNumbering="Sequence" concurrentWrites="true" keepFileOpen="false" encoding="iso-8859-2"/> </target> </targets> <rules> <logger name="*" minlevel="Debug" writeTo="file" /> </rules> </nlog>
在此配置中,我已设置异步日志记录,并带有日志存档。
标签简要介绍如下:
- <targets /> – 定义日志目标/输出
- <rules /> – 定义日志路由规则
- <extensions /> – 从 *.dll 文件加载 NLog 扩展
- <include /> – 包含外部配置文件
- <variable /> – 设置配置变量的值
将以下 appsettings 添加到 web.config 以开启/关闭日志记录。
<appSettings> <add key="IsEventLogOn" value="true" /> </appSettings>
我将添加 RIA 服务以接收来自 Silverlight 项目的日志请求。
在 Web 项目中添加空的 RIA 服务 “LoggingService.cs”。
在 WCF RIA 服务中编写以下方法。
using NLog; //在命名空间部分添加 private static readonly Logger Logger = LogManager.GetLogger("LoggingService"); [Invoke] public string GetLogONOFFFlag() { string flag = ConfigurationManager.AppSettings.Get("IsEventLogOn"); return flag; } protected override void OnError(DomainServiceErrorInfo errorInfo) { //记录异常 errorInfo.Error LogException("BriteDomainService RIA 服务中发生错误。", errorInfo.ToString()); base.OnError(errorInfo); } [Invoke] public void LogException(string errorCommentOrType, string Detail) { string errorMessage = String.Empty; string strUser = string.Empty; try { //以下获取用户名的代码仅在连接字符串中设置 ApplicationServices 时才有效。我将在下一个主题中介绍它 if (this.ServiceContext.User != null) if (this.ServiceContext.User.Identity != null) strUser = this.ServiceContext.User.Identity.Name; Detail = " [用户名: " + strUser + "] " + "时间: " + DateTime.Now.ToString() + " " + Detail; } catch (Exception ex) { Logger.Error("日志记录错误: " + ex); } finally { errorMessage = errorCommentOrType + " - " + Detail; switch (errorCommentOrType) { case "Fatal": Logger.Fatal(errorMessage); break; case "Error": Logger.Error(errorMessage); break; case "Warn": Logger.Warn(errorMessage); break; case "Info": Logger.Info(errorMessage); break; case "Debug": Logger.Debug(errorMessage); break; case "Trace": Logger.Trace(errorMessage); break; default: Logger.Error(errorMessage); break; }
Silverlight 客户端
在“app.xaml.cs”中声明“IsEventLogOn”属性。此属性将保存日志记录是开启还是关闭。
public bool IsEventLogOn { get; set; }
在“Application_UserLoaded”内部编写以下行以调用 RIA 服务获取“IsEventLogOn”值。
//调用 RIA 服务获取日志开关标志 var context = new BusinessAppMVVM.Web.Services.LoggingContext(); context.GetLogONOFFFlag(GetLogONOFFFlagCompleted, null);
将“GetLogONOFFFlagCompleted”定义如下。
private void GetLogONOFFFlagCompleted(InvokeOperation<string> args) { try { bool b = false; bool.TryParse(args.Value, out b); IsEventLogOn = b; } catch (Exception ex) { // } }
在“Helpers”文件夹中添加“LoggerManager”类文件。我将使用此类将错误发送到日志服务。代码可能如下所示。
public class LoggerManager { /// <summary> /// 将错误和活动日志写入日志文件。 /// </summary> /// <param name="errorCommentOrType">错误注释或错误类型,或事件名称</param> /// <param name="errorDetails">错误详细信息</param> /// <returns>bool</returns> public static bool WriteLog(string errorCommentOrType, string errorDetails) { try { MessageBox.Show("应用程序中发生了一些错误。请刷新后重试。" + errorDetails); if (((App)Application.Current).IsEventLogOn) { LoggingContext logErrorServiceClient = new LoggingContext(); logErrorServiceClient.LogException(errorCommentOrType, errorDetails, invokeOperation => { if (invokeOperation.HasError) { MessageBox.Show("记录错误时发生了一些错误!"); } else MessageBox.Show(@"错误已记录在 BusinessAppMVVM\BusinessAppMVVM.Web\logs\。"); }, null); } return true; } catch (Exception ex) { return false; } } } /// <summary> /// 日志类型 /// </summary> public enum LogType { DEBUG, ERROR, FATAL, INFO, WARN }
现在我将编写测试代码。将按钮控件添加到“Home.xaml”。在按钮点击事件上编写以下代码行。
private void button1_Click(object sender, System.Windows.RoutedEventArgs e) { try { //手动生成错误以测试错误日志记录 throw new Exception(); } catch (Exception ex) { LoggerManager.WriteLog(LogType.ERROR.ToString(), ex.ToString()); } }
根据日志类型生成日志文件。所以你也可以用它来调试信息。你已经看到这个日志记录过程可以配置为开启/关闭。
运行应用程序并单击按钮。
转到日志文件夹并验证日志文件。是的,您做到了。
总结
在本文中,我刚刚演示了如何使用 NLog 将 Silverlight 客户端错误记录到服务器。您可以下载本文随附的源代码。我使用 RIA 服务在 web 文件夹中进行日志记录。是使用 WCF 服务还是 RIA 服务进行数据库交互完全由您决定。如果您想使用 WCF 服务进行数据库交互,可以参考我的另一篇文章。我还将附带 WCF 解决方案供您参考。
请评论您的建议和改进,以便其他人受益。
祝您编码愉快!!