2012-07-28 23:08:02 +06:00
using System ;
2016-01-22 17:27:27 +01:00
using System.Collections.Generic ;
2015-01-16 12:07:29 +11:00
using System.ComponentModel ;
2012-07-28 23:08:02 +06:00
using System.Diagnostics ;
2013-05-14 13:39:55 -10:00
using System.Web ;
2012-07-28 23:08:02 +06:00
using Umbraco.Core.Logging ;
2013-05-13 21:11:03 -10:00
using Umbraco.Core.Profiling ;
2012-07-28 23:08:02 +06:00
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
{
2016-01-22 17:27:27 +01:00
private readonly ILogger _logger ;
private readonly LogType ? _logType ;
private readonly IProfiler _profiler ;
private readonly Type _loggerType ;
private readonly string _endMessage ;
private readonly IDisposable _profilerStep ;
2015-01-16 12:07:29 +11:00
private readonly Stopwatch _stopwatch = Stopwatch . StartNew ( ) ;
2012-07-28 23:08:02 +06:00
private readonly Action < long > _callback ;
2015-01-16 12:07:29 +11:00
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" ) ;
2016-01-22 17:27:27 +01:00
_logger = logger ;
_logType = logType ;
_profiler = profiler ;
_loggerType = loggerType ;
_endMessage = endMessage ;
2015-01-16 12:07:29 +11:00
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 )
{
2016-01-22 17:27:27 +01:00
_profilerStep = profiler . Step ( loggerType , startMessage ) ;
2015-01-16 12:07:29 +11:00
}
}
2015-01-16 12:29:27 +11:00
protected internal DisposableTimer ( Action < long > callback )
2015-01-16 12:07:29 +11:00
{
if ( callback = = null ) throw new ArgumentNullException ( "callback" ) ;
_callback = callback ;
}
2013-05-13 21:11:03 -10:00
2015-01-16 12:07:29 +11:00
public Stopwatch Stopwatch
2012-07-28 23:08:02 +06:00
{
get { return _stopwatch ; }
}
/// <summary>
/// Starts the timer and invokes the specified callback upon disposal.
/// </summary>
/// <param name="callback">The callback.</param>
/// <returns></returns>
2013-05-14 13:39:55 -10:00
[Obsolete("Use either TraceDuration or DebugDuration instead of using Start")]
2012-07-28 23:08:02 +06:00
public static DisposableTimer Start ( Action < long > callback )
{
return new DisposableTimer ( callback ) ;
}
2013-05-13 21:11:03 -10:00
#region TraceDuration
2015-01-16 12:07:29 +11:00
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use the other methods that specify strings instead of Func")]
2013-05-13 21:11:03 -10:00
public static DisposableTimer TraceDuration < T > ( Func < string > startMessage , Func < string > completeMessage )
{
return TraceDuration ( typeof ( T ) , startMessage , completeMessage ) ;
}
2012-11-27 10:42:22 +05:00
2015-01-16 12:07:29 +11:00
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use the other methods that specify strings instead of Func")]
2013-05-13 21:11:03 -10:00
public static DisposableTimer TraceDuration ( Type loggerType , Func < string > startMessage , Func < string > completeMessage )
{
2015-01-16 12:07:29 +11:00
return new DisposableTimer (
LoggerResolver . Current . Logger ,
LogType . Info ,
ProfilerResolver . HasCurrent ? ProfilerResolver . Current . Profiler : null ,
loggerType ,
startMessage ( ) ,
completeMessage ( ) ) ;
2013-05-13 21:11:03 -10:00
}
2012-07-28 23:08:02 +06:00
2013-05-13 21:11:03 -10:00
/// <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>
2015-01-16 12:07:29 +11:00
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
2013-05-13 21:11:03 -10:00
public static DisposableTimer TraceDuration < T > ( string startMessage , string completeMessage )
{
return TraceDuration ( typeof ( T ) , startMessage , completeMessage ) ;
}
2012-07-28 23:08:02 +06:00
2015-01-16 12:07:29 +11:00
/// <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")]
2013-05-13 22:13:52 -10:00
public static DisposableTimer TraceDuration < T > ( string startMessage )
{
return TraceDuration ( typeof ( T ) , startMessage , "Complete" ) ;
}
2013-05-13 21:11:03 -10:00
/// <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>
2015-01-16 12:07:29 +11:00
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
2013-05-13 21:11:03 -10:00
public static DisposableTimer TraceDuration ( Type loggerType , string startMessage , string completeMessage )
{
2015-01-16 12:07:29 +11:00
return new DisposableTimer (
LoggerResolver . Current . Logger ,
LogType . Info ,
ProfilerResolver . HasCurrent ? ProfilerResolver . Current . Profiler : null ,
loggerType ,
startMessage ,
completeMessage ) ;
}
2013-05-13 21:11:03 -10:00
#endregion
2012-07-30 22:52:59 +06:00
2013-05-13 21:11:03 -10:00
#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>
2015-01-16 12:07:29 +11:00
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
2013-05-13 21:11:03 -10:00
public static DisposableTimer DebugDuration < T > ( string startMessage , string completeMessage )
{
return DebugDuration ( typeof ( T ) , startMessage , completeMessage ) ;
}
2012-11-20 08:34:32 -01:00
2013-05-13 21:11:03 -10:00
/// <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>
2015-01-16 12:07:29 +11:00
[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")]
2013-05-13 21:11:03 -10:00
public static DisposableTimer DebugDuration < T > ( Func < string > startMessage , Func < string > completeMessage )
{
return DebugDuration ( typeof ( T ) , startMessage , completeMessage ) ;
}
2012-07-30 22:52:59 +06:00
2013-05-13 21:11:03 -10:00
/// <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>
2015-01-16 12:07:29 +11:00
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
2013-05-13 21:11:03 -10:00
public static DisposableTimer DebugDuration ( Type loggerType , string startMessage , string completeMessage )
{
2015-01-16 12:07:29 +11:00
return new DisposableTimer (
LoggerResolver . Current . Logger ,
LogType . Debug ,
ProfilerResolver . HasCurrent ? ProfilerResolver . Current . Profiler : null ,
loggerType ,
startMessage ,
completeMessage ) ;
2013-05-13 21:11:03 -10:00
}
2015-01-16 12:07:29 +11:00
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use the other methods that specify strings instead of Func")]
2013-05-13 21:11:03 -10:00
public static DisposableTimer DebugDuration ( Type loggerType , Func < string > startMessage , Func < string > completeMessage )
{
2015-01-16 12:07:29 +11:00
return new DisposableTimer (
LoggerResolver . Current . Logger ,
LogType . Debug ,
ProfilerResolver . HasCurrent ? ProfilerResolver . Current . Profiler : null ,
loggerType ,
startMessage ( ) ,
completeMessage ( ) ) ;
2013-05-13 21:11:03 -10:00
}
#endregion
2012-11-20 08:34:32 -01:00
2012-07-28 23:08:02 +06:00
/// <summary>
/// Handles the disposal of resources. Derived from abstract class <see cref="DisposableObject"/> which handles common required locking logic.
/// </summary>
protected override void DisposeResources ( )
{
2016-01-22 17:27:27 +01:00
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 ) ;
}
2012-07-28 23:08:02 +06:00
}
2013-05-14 13:39:55 -10:00
2012-07-28 23:08:02 +06:00
}
}