工厂方法模式实现多功能日志记录

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:

有时,我们在开发的时候,会遇到一些关于日志记录的功能。并且,它们可能是独立于系统业务逻辑的,那么我们就可以将日志做成组件的形式,以方便复用。

以下采用工厂方法模式,来实现日志组件的设计,并保证对功能的扩展不会改变已有的实现。

我们实现三种日志记录类型:错误日志记录、按钮点击日志记录、操作日志记录。

首先,我们创建一个“抽象工厂”【其实是各实例工厂都必须实现的Log接口】,既然是日志记录,那么就需要有日志的实体了。也就是LogEntity,它是一个“抽象实体”,因为不同类型的日志,需要不同的日志实体,所以这里采用LogEntity作为抽象实体,来派生出各具体类型的日志实体。

实现如下:

public interface ILogFactory
    {
        void Log(LogEntity logEntity);
    }

/// <summary>
    /// 日志实体(抽象基类)
    /// </summary>
    public abstract class LogEntity
    {
        public override string ToString()
        {
            return "LogEntity(abstract class)";
        }
    }

以下是各个实例工厂、和日志实体,实现各自的日志记录逻辑:

/// <summary>
    /// 记录错误日志实体类
    /// </summary>
    public class ErrorEntity:LogEntity
    {
        /// <summary>
        /// 编号
        /// </summary>
        public string ID { get; set; }

        /// <summary>
        /// 用户编号
        /// </summary>
        public string UserID { get; set; }

        /// <summary>
        /// 页面URL
        /// </summary>
        public string PageUrl { get; set; }

        /// <summary>
        /// 错误信息
        /// </summary>
        public string Msg { get; set; }

        /// <summary>
        /// 发生时间
        /// </summary>
        public DateTime OperateTime { get; set; }

    }

public class ErrorFactory : ILogFactory
    {

        private const string FullClassName = "LogComponent.ErrorFactory";

        public void Log(LogEntity logEntity)
        {
            #region check args
            if (logEntity == null)
            {
                throw new ArgumentNullException(string.Format("The Method in {0} occur ArgumentNullException", FullClassName));
            }

            ErrorEntity innerEntity = logEntity as ErrorEntity;

            if (innerEntity == null)
            {
                throw new NullReferenceException(string.Format("The Method in {0} occur NullReferenceException.Because of converting type.", FullClassName));
            }

            if (string.IsNullOrEmpty(innerEntity.Msg))
            {
                throw new Exception(string.Format("The Method in {0} occur logic Exception. Because of the error message is not nullable", FullClassName));
            }
            #endregion

            //记录日志
            string sql = @"INSERT INTO SYSTEMERRORINFO(SE_USERID,SE_PAGEURL,SE_MESSAGE,SE_OPERATETIME) values (:SE_USERID,:SE_PAGEURL,:SE_MESSAGE,:SE_OPERATETIME)";
            OracleParameter[] parameters = new OracleParameter[]
            {
                new OracleParameter(":SE_USERID",innerEntity.UserID==null?"":innerEntity.UserID),
                new OracleParameter(":SE_PAGEURL",innerEntity.PageUrl==null?"":innerEntity.PageUrl),
                new OracleParameter(":SE_MESSAGE",innerEntity.Msg==null?"":innerEntity.Msg),
                new OracleParameter(":SE_OPERATETIME",innerEntity.OperateTime==DateTime.MinValue?DateTime.Now:innerEntity.OperateTime)
             };

            OracleHelper.ExecuteNonQuery(OracleHelper.ConnectionStringLocalTransaction, CommandType.Text, sql, parameters);

        }

    }

/// <summary>
    /// 点击按钮统计--其中ButtonName为必填字段
    /// </summary>
    public class ClickCountEntity:LogEntity
    {
        /// <summary>
        /// 记录编号
        /// </summary>
        public string ID { get; set; }

        /// <summary>
        /// 用户ID
        /// </summary>
        public string UserID { get; set; }

        /// <summary>
        /// 页面Url
        /// </summary>
        public string PageUrl { get; set; }

        /// <summary>
        /// 操作时间
        /// </summary>
        public DateTime OperateTime { get; set; }

        /// <summary>
        /// 路径名称
        /// </summary>
        public string PathName { get; set; }

        /// <summary>
        /// 按钮名称
        /// </summary>
        public string ButtonName { get; set; }
    }

public class ClickCountFactory:ILogFactory
    {

        private const string FullClassName = "LogComponent.ClickCountFactory";
        private ErrorEntity errorEntity = null;

        public void Log(LogEntity logEntity)
        {
            //check args
            if (logEntity==null)
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = string.Format("The method in {0} occur ArgumentNullException.Because of the arg: logEntity is not nullable.", FullClassName);
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw new ArgumentNullException(string.Format("The method in {0} occur ArgumentNullException.Because of the arg: logEntity is not nullable.", FullClassName));
            }

            ClickCountEntity innerEntity = logEntity as ClickCountEntity;
            if (innerEntity==null)
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = string.Format("The method in {0} occur NullReferenceException.Becaues of converting type", FullClassName);
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw new NullReferenceException(string.Format("The method in {0} occur NullReferenceException..Becaues of converting type", FullClassName));
            }

            if (String.IsNullOrEmpty(innerEntity.ButtonName))
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = string.Format("The method in {0} occur Exception.Because of the field ButtonName is not nullable.", FullClassName);
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw new Exception(string.Format("The method in {0} occur Exception.Because of the field ButtonName is not nullable.", FullClassName));
            }

            string sql = @"INSERT INTO buttonclickstatistic
                           (bs_userid, bs_pageurl, bs_buttonid, bs_operatetime, bs_pathname, bs_buttonname)
                           VALUES
                           (:v_bs_userid, :v_bs_pageurl, :v_bs_buttonid, :v_bs_operatetime, :v_bs_pathname, :v_bs_buttonname)";

            OracleParameter[] parameters = new OracleParameter[]{
               new OracleParameter(":v_bs_userid",innerEntity.UserID==null?"":innerEntity.UserID),
               new OracleParameter(":v_bs_pageurl",innerEntity.PageUrl==null?"":innerEntity.PageUrl),
               new OracleParameter(":v_bs_buttonid",innerEntity.ID==null?"":innerEntity.ID),
               new OracleParameter(":v_bs_operatetime",innerEntity.OperateTime),
               new OracleParameter(":v_bs_pathname",innerEntity.PathName==null?"":innerEntity.PathName),
               new OracleParameter(":v_bs_buttonname",innerEntity.ButtonName)
            };

            try
            {
                OracleHelper.ExecuteNonQuery(OracleHelper.ConnectionStringLocalTransaction, CommandType.Text, sql, parameters);
            }
            catch (Exception ex)
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = ex.Message + ex.StackTrace;
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw;
            }
            
        }

    }

/// <summary>
    /// 操作日志实体类--其中Msg为必填字段
    /// </summary>
    public class OperatingEntity:LogEntity
    {
        /// <summary>
        /// 记录编号
        /// </summary>
        public string ID { get; set; }

        /// <summary>
        /// 用户Id
        /// </summary>
        public string UserID { get; set; }

        /// <summary>
        /// 操作日志
        /// </summary>
        public string Msg { get; set; }

        /// <summary>
        /// 操作时间
        /// </summary>
        public DateTime OperatingTime { get; set; }

        /// <summary>
        /// 登陆时间
        /// </summary>
        public DateTime LoginTime { get; set; }

        /// <summary>
        /// 下线时间
        /// </summary>
        public DateTime LogoutTime { get; set; }


    }

public class OperatingFactory:ILogFactory
    {
        private const string FullClassName = "LogComponent.OperatingFactory";
        private ErrorEntity errorEntity = null;

        public void Log(LogEntity logEntity)
        {
            //check args
            if (logEntity==null)
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = string.Format("The method in {0} occur ArgumentNullException.Because of the arg: {1} is not nullable", FullClassName, "logEntity");
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw new ArgumentNullException(string.Format("The method in {0} occur ArgumentNullException.Because of the arg: {1} is not nullable", FullClassName, "logEntity"));

            }

            OperatingEntity innerEntity = logEntity as OperatingEntity;
            if (innerEntity==null)
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = string.Format("The method in {0} occur NullReferenceException.Because of Converting type.", FullClassName);
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw new NullReferenceException(string.Format("The method in {0} occur NullReferenceException.Because of Converting type.", FullClassName));
            }

            if (string.IsNullOrEmpty(innerEntity.Msg))
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = string.Format("The method in {0} occur Exception.Because of the field:Msg is not nullable.",FullClassName);
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw new Exception(string.Format("The method in {0} occur Exception.Because of the field:Msg is not nullable.", FullClassName));
            }

            //记录日志
            string sql = @"INSERT INTO operatinglog(ol_uf_id,ol_msg,ol_op_time,ol_li_time,ol_lo_time) 
                                             VALUES(:ol_uf_id,:ol_msg,:ol_op_time,:ol_li_time,:ol_lo_time)";

            OracleParameter[] paras = new OracleParameter[]
            {
                new OracleParameter(":ol_uf_id",innerEntity.UserID==null?"":innerEntity.UserID),
                new OracleParameter(":ol_msg",innerEntity.Msg),
                new OracleParameter(":ol_op_time",innerEntity.OperatingTime),
                new OracleParameter(":ol_li_time",innerEntity.LoginTime),
                new OracleParameter(":ol_lo_time",innerEntity.LogoutTime),
            };

            try
            {
                OracleHelper.ExecuteNonQuery(OracleHelper.ConnectionStringLocalTransaction, CommandType.Text, sql, paras);
            }
            catch (Exception ex)
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = ex.Message + ex.StackTrace;
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw;
            }
            
        }
    }

在客户端调用的时候,你需要先new 一个你需要的具体的日志实体,然后设置它的属性,比如:

OperatingEntity entity=new OperatingEntity();

//set Property

entity.OperatingTime=DateTime.Now;

.....

然后提供你的实例工厂:

ILogFactory factory=new OperatingFactory();

factory.Log(entity);


扩展的时候,你需要构建你新的日志实体类和新的实例工厂,来实现你的记录逻辑。

原有的实现都无需改动。




原文发布时间为:2011-07-24


本文作者:vinoYang


本文来自云栖社区合作伙伴CSDN博客,了解相关信息可以关注CSDN博客。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
1月前
|
Rust 前端开发 JavaScript
Tauri 开发实践 — Tauri 日志记录功能开发
本文介绍了如何为 Tauri 应用配置日志记录。Tauri 是一个利用 Web 技术构建桌面应用的框架。文章详细说明了如何在 Rust 和 JavaScript 代码中设置和集成日志记录,并控制日志输出。通过添加 `log` crate 和 Tauri 日志插件,可以轻松实现多平台日志记录,包括控制台输出、Webview 控制台和日志文件。文章还展示了如何调整日志级别以优化输出内容。配置完成后,日志记录功能将显著提升开发体验和程序稳定性。
65 1
Tauri 开发实践 — Tauri 日志记录功能开发
|
3月前
|
Kubernetes Ubuntu Windows
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
131 3
|
3月前
|
SQL 存储 JSON
更快更强,SLS 推出高性能 SPL 日志查询模式
从海量的日志数据中,按照各种灵活的条件进行即时查询搜索,是可观测场景下的基本需求。本文介绍了 SLS 新推出的高性能 SPL 日志查询模式,支持 Unix 风格级联管道式语法,以及各种丰富的 SQL 处理函数。同时通过计算下推、向量化计算等优化,使得 SPL 查询可以在数秒内处理亿级数据,并支持 SPL 过滤结果分布图、随机翻页等特性。
12001 108
|
2月前
|
存储 监控 数据可视化
SLS 虽然不是直接使用 OSS 作为底层存储,但它凭借自身独特的存储架构和功能,为用户提供了一种专业、高效的日志服务解决方案。
【9月更文挑战第2天】SLS 虽然不是直接使用 OSS 作为底层存储,但它凭借自身独特的存储架构和功能,为用户提供了一种专业、高效的日志服务解决方案。
150 9
|
3月前
|
存储 监控 Serverless
函数计算发布功能问题之用户在使用主流函数计算产品的日志服务时可能会遇到使用成本的问题如何解决
函数计算发布功能问题之用户在使用主流函数计算产品的日志服务时可能会遇到使用成本的问题如何解决
|
3月前
|
监控 Serverless 开发者
函数计算发布功能问题之查看函数的调用日志的问题如何解决
函数计算发布功能问题之查看函数的调用日志的问题如何解决
|
3月前
|
数据可视化 应用服务中间件 Apache
优化集中式日志记录的方法:添加 Logstash 过滤器
优化集中式日志记录的方法:添加 Logstash 过滤器
45 1
|
3月前
|
开发者 前端开发 编解码
Vaadin解锁移动适配新境界:一招制胜,让你的应用征服所有屏幕!
【8月更文挑战第31天】在移动互联网时代,跨平台应用开发备受青睐。作为一款基于Java的Web应用框架,Vaadin凭借其组件化设计和强大的服务器端渲染能力,助力开发者轻松构建多设备适应的Web应用。本文探讨Vaadin与移动设备的适配策略,包括响应式布局、CSS媒体查询、TouchKit插件及服务器端优化,帮助开发者打造美观且实用的移动端体验。通过这些工具和策略的应用,可有效应对屏幕尺寸、分辨率及操作系统的多样性挑战,满足广大移动用户的使用需求。
65 0
|
3月前
|
存储 运维 监控
Entity Framework Core 实现审计日志记录超棒!多种方法助你跟踪数据变化、监控操作,超实用!
【8月更文挑战第31天】在软件开发中,审计日志记录对于跟踪数据变化、监控用户操作及故障排查至关重要。Entity Framework Core (EF Core) 作为强大的对象关系映射框架,提供了多种实现审计日志记录的方法。例如,可以使用 EF Core 的拦截器在数据库操作前后执行自定义逻辑,记录操作类型、时间和执行用户等信息。此外,也可通过在实体类中添加审计属性(如 `CreatedBy`、`CreatedDate` 等),并在保存实体时更新这些属性来记录审计信息。这两种方法都能有效帮助我们追踪数据变更并满足合规性和安全性需求。
72 0
|
3月前
|
SQL JavaScript 前端开发
【Azure 应用服务】Azure JS Function 异步方法中执行SQL查询后,Callback函数中日志无法输出问题
【Azure 应用服务】Azure JS Function 异步方法中执行SQL查询后,Callback函数中日志无法输出问题