253 lines
9.8 KiB
C#
253 lines
9.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Web;
|
|
using Umbraco.Core.Logging;
|
|
using Umbraco.Core.Profiling;
|
|
|
|
namespace Umbraco.Core
|
|
{
|
|
/// <summary>
|
|
/// Starts the timer and invokes a callback upon disposal. Provides a simple way of timing an operation by wrapping it in a <code>using</code> (C#) statement.
|
|
/// </summary>
|
|
public class DisposableTimer : DisposableObject
|
|
{
|
|
private readonly ILogger _logger;
|
|
private readonly LogType? _logType;
|
|
private readonly IProfiler _profiler;
|
|
private readonly Type _loggerType;
|
|
private readonly string _endMessage;
|
|
private readonly IDisposable _profilerStep;
|
|
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
|
|
private readonly Action<long> _callback;
|
|
|
|
internal enum LogType
|
|
{
|
|
Debug, Info
|
|
}
|
|
|
|
internal DisposableTimer(ILogger logger, LogType logType, IProfiler profiler, Type loggerType, string startMessage, string endMessage)
|
|
{
|
|
if (logger == null) throw new ArgumentNullException("logger");
|
|
if (loggerType == null) throw new ArgumentNullException("loggerType");
|
|
|
|
_logger = logger;
|
|
_logType = logType;
|
|
_profiler = profiler;
|
|
_loggerType = loggerType;
|
|
_endMessage = endMessage;
|
|
|
|
switch (logType)
|
|
{
|
|
case LogType.Debug:
|
|
logger.Debug(loggerType, startMessage);
|
|
break;
|
|
case LogType.Info:
|
|
logger.Info(loggerType, startMessage);
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException("logType");
|
|
}
|
|
|
|
if (profiler != null)
|
|
{
|
|
_profilerStep = profiler.Step(loggerType, startMessage);
|
|
}
|
|
}
|
|
|
|
protected internal DisposableTimer(Action<long> callback)
|
|
{
|
|
if (callback == null) throw new ArgumentNullException("callback");
|
|
_callback = callback;
|
|
}
|
|
|
|
public Stopwatch Stopwatch
|
|
{
|
|
get { return _stopwatch; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Starts the timer and invokes the specified callback upon disposal.
|
|
/// </summary>
|
|
/// <param name="callback">The callback.</param>
|
|
/// <returns></returns>
|
|
[Obsolete("Use either TraceDuration or DebugDuration instead of using Start")]
|
|
public static DisposableTimer Start(Action<long> callback)
|
|
{
|
|
return new DisposableTimer(callback);
|
|
}
|
|
|
|
#region TraceDuration
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
[Obsolete("Use the other methods that specify strings instead of Func")]
|
|
public static DisposableTimer TraceDuration<T>(Func<string> startMessage, Func<string> completeMessage)
|
|
{
|
|
return TraceDuration(typeof(T), startMessage, completeMessage);
|
|
}
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
[Obsolete("Use the other methods that specify strings instead of Func")]
|
|
public static DisposableTimer TraceDuration(Type loggerType, Func<string> startMessage, Func<string> completeMessage)
|
|
{
|
|
return new DisposableTimer(
|
|
LoggerResolver.Current.Logger,
|
|
LogType.Info,
|
|
ProfilerResolver.HasCurrent ? ProfilerResolver.Current.Profiler : null,
|
|
loggerType,
|
|
startMessage(),
|
|
completeMessage());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="startMessage"></param>
|
|
/// <param name="completeMessage"></param>
|
|
/// <returns></returns>
|
|
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
|
|
public static DisposableTimer TraceDuration<T>(string startMessage, string completeMessage)
|
|
{
|
|
return TraceDuration(typeof(T), startMessage, completeMessage);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="startMessage"></param>
|
|
/// <returns></returns>
|
|
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
|
|
public static DisposableTimer TraceDuration<T>(string startMessage)
|
|
{
|
|
return TraceDuration(typeof(T), startMessage, "Complete");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
|
|
/// </summary>
|
|
/// <param name="loggerType"></param>
|
|
/// <param name="startMessage"></param>
|
|
/// <param name="completeMessage"></param>
|
|
/// <returns></returns>
|
|
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
|
|
public static DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage)
|
|
{
|
|
return new DisposableTimer(
|
|
LoggerResolver.Current.Logger,
|
|
LogType.Info,
|
|
ProfilerResolver.HasCurrent ? ProfilerResolver.Current.Profiler : null,
|
|
loggerType,
|
|
startMessage,
|
|
completeMessage);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region DebugDuration
|
|
/// <summary>
|
|
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="startMessage"></param>
|
|
/// <param name="completeMessage"></param>
|
|
/// <returns></returns>
|
|
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
|
|
public static DisposableTimer DebugDuration<T>(string startMessage, string completeMessage)
|
|
{
|
|
return DebugDuration(typeof(T), startMessage, completeMessage);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="startMessage"></param>
|
|
/// <returns></returns>
|
|
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
|
|
public static DisposableTimer DebugDuration<T>(string startMessage)
|
|
{
|
|
return DebugDuration(typeof(T), startMessage, "Complete");
|
|
}
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
[Obsolete("Use the other methods that specify strings instead of Func")]
|
|
public static DisposableTimer DebugDuration<T>(Func<string> startMessage, Func<string> completeMessage)
|
|
{
|
|
return DebugDuration(typeof(T), startMessage, completeMessage);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
|
/// </summary>
|
|
/// <param name="loggerType"></param>
|
|
/// <param name="startMessage"></param>
|
|
/// <param name="completeMessage"></param>
|
|
/// <returns></returns>
|
|
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
|
|
public static DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage)
|
|
{
|
|
return new DisposableTimer(
|
|
LoggerResolver.Current.Logger,
|
|
LogType.Debug,
|
|
ProfilerResolver.HasCurrent ? ProfilerResolver.Current.Profiler : null,
|
|
loggerType,
|
|
startMessage,
|
|
completeMessage);
|
|
}
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
[Obsolete("Use the other methods that specify strings instead of Func")]
|
|
public static DisposableTimer DebugDuration(Type loggerType, Func<string> startMessage, Func<string> completeMessage)
|
|
{
|
|
return new DisposableTimer(
|
|
LoggerResolver.Current.Logger,
|
|
LogType.Debug,
|
|
ProfilerResolver.HasCurrent ? ProfilerResolver.Current.Profiler : null,
|
|
loggerType,
|
|
startMessage(),
|
|
completeMessage());
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Handles the disposal of resources. Derived from abstract class <see cref="DisposableObject"/> which handles common required locking logic.
|
|
/// </summary>
|
|
protected override void DisposeResources()
|
|
{
|
|
if (_profiler != null)
|
|
{
|
|
_profiler.DisposeIfDisposable();
|
|
}
|
|
|
|
if (_profilerStep != null)
|
|
{
|
|
_profilerStep.Dispose();
|
|
}
|
|
|
|
if (_logType.HasValue && _endMessage.IsNullOrWhiteSpace() == false && _loggerType != null && _logger != null)
|
|
{
|
|
switch (_logType)
|
|
{
|
|
case LogType.Debug:
|
|
_logger.Debug(_loggerType, () => _endMessage + " (took " + Stopwatch.ElapsedMilliseconds + "ms)");
|
|
break;
|
|
case LogType.Info:
|
|
_logger.Info(_loggerType, () => _endMessage + " (took " + Stopwatch.ElapsedMilliseconds + "ms)");
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException("logType");
|
|
}
|
|
}
|
|
|
|
if (_callback != null)
|
|
{
|
|
_callback.Invoke(Stopwatch.ElapsedMilliseconds);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
} |