一个简单的封装 .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
}

 

posted on 2011-01-19 15:01  听说读写  阅读(976)  评论(0编辑  收藏  举报

导航