Silverlight应用的服务器端日志记录机制

在开发应用程序时,日志记录是一个重要的功能,它可以帮助开发者追踪错误、监控应用行为以及分析用户行为。对于Silverlight应用,实现一个有效的服务器端日志记录机制尤其重要,因为它可以集中管理日志,并且不会影响客户端的性能。本文将展示如何使用NLog2.0来实现这一机制。

为什么选择NLog

日志记录领域,NLog和Log4Net是两个非常流行的平台。NLog 2.0的发布专注于为新平台(如Silverlight、.NET Framework 4、Windows Phone 7.x)提供支持,改进日志架构和管理性,并解决用户最常报告的问题。它完全支持异步操作,因此对于Silverlight应用来说,NLog是最佳选择。

日志记录的两种方式

在Silverlight应用中,可以选择客户端日志记录或服务器端日志记录。客户端日志记录会降低性能,并且无法在集中的地方查看日志。因此,服务器端日志记录是一个更优的选择。

为了实现这个应用,将使用以下技术:

  • Silverlight5作为客户端层
  • WCF服务 - HTTP绑定(如果需要与数据库交互,可以选择使用)
  • WCF RIA服务 V1.0 SP2
  • NLog 2.0(可以从下载)

创建Silverlight业务应用

首先,创建一个新的Silverlight业务应用,并将其命名为‘BusinessAppMVVM’。

Web项目配置

接下来,将在Web项目中添加NLog.Config文件。将以下代码复制/粘贴到NLog.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"> <targets> <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 /> - 设置配置变量的值

启用/禁用日志记录

在web.config文件中添加以下appSettings,以启用/禁用日志记录

<appSettings> <add key="IsEventLogOn" value="true" /> </appSettings>

添加RIA服务

接下来,将添加一个空的RIA服务‘LoggingService.cs’到Web项目中,并在WCF RIA服务中编写以下方法。

using NLog; // Add in namespace section 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) { // Log exception errorInfo.Error LogException("Error in BriteDomainService RIA Service. ", errorInfo.ToString()); base.OnError(errorInfo); } [Invoke] public void LogException(string errorCommentOrType, string Detail) { string errorMessage = String.Empty; string strUser = string.Empty; try { if (this.ServiceContext.User != null) if (this.ServiceContext.User.Identity != null) strUser = this.ServiceContext.User.Identity.Name; Detail = "[UserName: " + strUser + "] Time: " + DateTime.Now.ToString() + " " + Detail; } catch (Exception ex) { Logger.Error("Logging 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’值。

var context = new BusinessAppMVVM.Web.Services.LoggingContext(); context.GetLogONOFFFlag(GetLogONOFFFlagCompleted, null);

定义‘GetLogONOFFFlagCompleted’方法如下:

private void GetLogONOFFFlagCompleted(InvokeOperation args) { try { bool b = false; bool.TryParse(args.Value, out b); IsEventLogOn = b; } catch (Exception ex) { // Handle exception } }

LoggerManager类

在‘Helpers’文件夹中添加‘LoggerManager’类文件。这个类将用于将错误发送到日志服务。代码如下:

public class LoggerManager { /// <summary> /// Writing the Error and Activity logs in the log files. /// </summary> /// <param name="errorCommentOrType">Error Comment or Error Type or in case of event enter Event Name</param> /// <param name="errorDetails">Error Details</param> /// <returns>bool</returns> public static bool WriteLog(string errorCommentOrType, string errorDetails) { try { MessageBox.Show("Some error is occured in application. Please try again after refresh. " + errorDetails); if (((App)Application.Current).IsEventLogOn) { LoggingContext logErrorServiceClient = new LoggingContext(); logErrorServiceClient.LogException(errorCommentOrType, errorDetails, invokeOperation => { if (invokeOperation.HasError) { MessageBox.Show("Some error is occurred while error logging!"); } else MessageBox.Show(@"Error is logged in BusinessAppMVVM\BusinessAppMVVM.Web\logs\."); }, null); } return true; } catch (Exception ex) { return false; } } }

日志类型

定义日志类型枚举:

public enum LogType { DEBUG, ERROR, FATAL, INFO, WARN }

测试代码

在‘Home.xaml’中添加按钮控件。在按钮点击事件中编写以下代码:

private void button1_Click(object sender, System.Windows.RoutedEventArgs e) { try { // Manually generating error to test error logging throw new Exception(); } catch (Exception ex) { LoggerManager.WriteLog(LogType.ERROR.ToString(), ex.ToString()); } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485