zoukankan      html  css  js  c++  java
  • 一个简单的封装 .net的日志功能

    因为项目需要 ,经常自己写一点工具类

    下面就是一个简单的日志类,支持多线程,不锁定文件,需要CLFS支持,性能非常好

    0警告 0stylecop


    代码
    // --------------------------------------------------------------------------------------------------------------------
    // <copyright file="Logger.cs" company="Clover">
    // Copyright (c) Clover, All Rights Reserved.
    // </copyright>
    // <summary>
    // Provides methods to write application logs based on a Common Log File System. This class cannot be inherited.
    // </summary>
    // --------------------------------------------------------------------------------------------------------------------

    namespace Clover
    {
    #region Using directives

    using System;
    using System.Configuration;
    using System.Globalization;
    using System.IO;
    using System.IO.Log;
    using System.Text;

    #endregion

    /// <summary>
    /// Encapsulates a type to write application logs based on a Common Log File System. This class cannot be inherited.
    /// </summary>
    public sealed class Logger : IDisposable
    {
    #region Constants and Fields

    /// <summary>
    /// The key of the configuration for base name.
    /// </summary>
    public const string BaseNameKey = "Clover.LogBaseName";

    /// <summary>
    /// The key of the configuration for base directory.
    /// </summary>
    public const string BasePathKey = "Clover.LogBasePath";

    /// <summary>
    /// The key of the configuration for extent size.
    /// </summary>
    public const string ExtentSizeKey = "Clover.ExtentSize";

    /// <summary>
    /// The default size for each log extent.
    /// </summary>
    private const int DefaultExtentSize = 10 * 1024 * 1024;

    /// <summary>
    /// The log record sequence object to write the log entries.
    /// </summary>
    private readonly LogRecordSequence _sequence;

    /// <summary>
    /// The log store to hold the log record sequence object.
    /// </summary>
    private readonly LogStore _store;

    #endregion

    #region Constructors and Destructors

    /// <summary>
    /// Initializes a new instance of the <see cref="Logger"/> class.
    /// </summary>
    /// <param name="basePath">
    /// The base path where the log files are resided.
    /// </param>
    /// <param name="baseName">
    /// The base name of the log files.
    /// </param>
    /// <param name="extentSize">
    /// Size of each log extent in bytes.
    /// </param>
    /// <exception cref="ArgumentNullException">
    /// <paramref name="basePath"/> is null, or <paramref name="baseName"/> is null.
    /// </exception>
    public Logger(string basePath, string baseName, int extentSize)
    {
    if (string.IsNullOrEmpty(basePath))
    {
    throw new ArgumentNullException("basePath");
    }

    if (string.IsNullOrEmpty(baseName))
    {
    throw new ArgumentNullException("baseName");
    }

    // If the base path doesn't exist, create it.
    if (!Directory.Exists(basePath))
    {
    Directory.CreateDirectory(basePath);
    }

    string fullPath = Path.Combine(basePath, baseName);
    this._store = new LogStore(fullPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
    this._sequence = new LogRecordSequence(this._store);
    this._sequence.RetryAppend = true;

    if (this._store.Extents.Count == 0)
    {
    this._store.Extents.Add(fullPath, extentSize);
    }
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="Logger"/> class.
    /// </summary>
    /// <param name="basePath">
    /// The base path where the log files are resided.
    /// </param>
    /// <param name="baseName">
    /// The base name of the log files.
    /// </param>
    /// <exception cref="ArgumentNullException">
    /// <paramref name="basePath"/> is null, or <paramref name="baseName"/> is null.
    /// </exception>
    public Logger(string basePath, string baseName)
    :
    this(basePath, baseName, Logger.DefaultExtentSize)
    {

    }

    /// <summary>
    /// Initializes a new instance of the <see cref="Logger"/> class by reading the arguments from the application
    /// configuration file.
    /// </summary>
    /// <exception cref="ArgumentNullException">
    /// One or more configuration values are not found in the application's configuration file.
    /// </exception>
    public Logger()
    :
    this(
    ConfigurationManager.AppSettings[Logger.BasePathKey],
    ConfigurationManager.AppSettings[Logger.BaseNameKey],
    Convert.ToInt32(ConfigurationManager.AppSettings[Logger.DefaultExtentSize]))
    {
    }

    #endregion

    #region Public Methods

    /// <summary>
    /// Writes the specified entry to the log store with format arguments.
    /// </summary>
    /// <param name="entry">
    /// The entry to write.
    /// </param>
    /// <param name="args">
    /// The arguments to format the entry.
    /// </param>
    /// <exception cref="ArgumentNullException">
    /// <paramref name="entry"/> is null.
    /// </exception>
    public void WriteEntry(string entry, params object[] args)
    {
    if (string.IsNullOrEmpty(entry))
    {
    throw new ArgumentNullException("entry");
    }

    entry
    = string.Format(CultureInfo.CurrentCulture, entry, args);
    this.WriteEntry(entry);
    }

    /// <summary>
    /// Writes the specified entry to the log store with format arguments.
    /// </summary>
    /// <param name="entry">
    /// The entry to write.
    /// </param>
    /// <exception cref="ArgumentNullException">
    /// <paramref name="entry"/> is null.
    /// </exception>
    public void WriteEntry(string entry)
    {
    if (string.IsNullOrEmpty(entry))
    {
    throw new ArgumentNullException("entry");
    }

    byte[] bytes = Encoding.Unicode.GetBytes(entry);
    this._sequence.Append(new ArraySegment<byte>(bytes), SequenceNumber.Invalid, SequenceNumber.Invalid, RecordAppendOptions.None);
    }

    #endregion

    #region Implemented Interfaces

    #region IDisposable

    /// <summary>
    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
    /// </summary>
    public void Dispose()
    {
    this.Dispose(true);
    GC.SuppressFinalize(
    this);
    }

    #endregion

    #endregion

    #region Methods

    /// <summary>
    /// Releases unmanaged and - optionally - managed resources
    /// </summary>
    /// <param name="disposing">
    /// <c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.
    /// </param>
    private void Dispose(bool disposing)
    {
    if (disposing)
    {
    if (this._sequence != null)
    {
    this._sequence.Dispose();
    }

    if (this._store != null)
    {
    this._store.Dispose();
    }
    }
    }

    #endregion
    }
    }

    以下是单元测试代码: 

    代码
    #region Using directives

    using System;

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System.Threading;

    #endregion

    /// <summary>
    /// Contains tests for the Log class.
    /// </summary>
    [TestClass]
    public class LoggerTest : UnitTestBase
    {
    /// <summary>
    /// The base path for log test.
    /// </summary>
    private readonly string _basePath = Environment.ExpandEnvironmentVariables(@"%UserProfile%\Documents\LogTest");

    /// <summary>
    /// The base name for log test.
    /// </summary>
    private const string BaseName = "MyLog";

    #region Public Methods

    /// <summary>
    /// Tests the Constructor.
    /// </summary>
    [TestMethod]
    public void ConstructorTest()
    {
    // Scenario 1: Create a normal Logger using parameterized constructor.
    Logger logger = new Logger(this._basePath, BaseName);
    Assert.IsNotNull(logger);

    // Scenario 2: Create a normal logger using default configuration.
    try
    {
    new Logger();
    Assert.Fail(
    "Expect ArgumentNullException or ArgumentOutOfRangeException");
    }
    catch (ArgumentOutOfRangeException)
    {
    Assert.IsTrue(
    true);
    }
    catch (ArgumentNullException)
    {
    Assert.IsTrue(
    true);
    }
    finally
    {
    logger.Dispose();
    }
    }

    /// <summary>
    /// Tests the WriteEntry method.
    /// </summary>
    [TestMethod]
    public void WriteEntryTest()
    {
    // Scenario 1: Write one entry.
    string content = "A quick brown fox jumps over the lazy dog";
    using (Logger logger = new Logger(this._basePath, BaseName))
    {
    logger.WriteEntry(content);
    Assert.IsTrue(
    true);

    // Scenario 2: Write 1,000,000 entries at a time.
    for (int i = 0; i < 1000000; i++)
    {
    logger.WriteEntry(content);
    }


    // Scenario 3: Write one entry with format.
    content = "{0} - {1}: {2}";
    logger.WriteEntry(content,
    1, 2, 3);

    }
    }



    #endregion
    }
  • 相关阅读:
    对百度搜索引擎的评论
    团队开发个人总结05
    Bootsrap下拉菜单实现Hover下拉效果
    C#抽奖优惠券生成唯一码方法
    js.live方法无效, 报错:uncaught TypeError: $(...).live is not a function
    SQL 插入一条自定义主键值的数据
    一款很简单的直接发送邮件功能
    SQL生成指定范围内随机值
    SQL(replace)替换字段中指定的字符
    SQL表中删除一列
  • 原文地址:https://www.cnblogs.com/PurpleTide/p/1939189.html
Copyright © 2011-2022 走看看