// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
namespace EpicGames.Core
{
///
/// Manages a status message for a long running operation, which can be updated with progress. Typically transient on consoles, and written to the same line.
///
public interface ILoggerProgress : IDisposable
{
///
/// Prefix message for the status
///
string Message
{
get;
}
///
/// The current
///
string Progress
{
get; set;
}
}
///
/// Extension methods for status objects
///
public static class LoggerProgressExtensions
{
///
/// Concrete implementation of
///
class LoggerProgress : ILoggerProgress
{
///
/// The logger to output to
///
private readonly ILogger _logger;
///
/// Prefix message for the status
///
public string Message
{
get;
}
///
/// The current
///
public string Progress
{
get => _progressInternal;
set
{
_progressInternal = value;
if (_timer.Elapsed > TimeSpan.FromSeconds(3.0))
{
_lastOutput = String.Empty;
Flush();
_timer.Restart();
}
}
}
///
/// The last string that was output
///
string _lastOutput = String.Empty;
///
/// Backing storage for the Progress string
///
string _progressInternal = String.Empty;
///
/// Timer since the last update
///
readonly Stopwatch _timer = Stopwatch.StartNew();
///
/// Constructor
///
/// The logger to write to
/// The base message to display
public LoggerProgress(ILogger logger, string message)
{
_logger = logger;
Message = message;
_progressInternal = String.Empty;
logger.LogInformation("{Progress}", message);
}
///
/// Dispose of this object
///
public void Dispose()
{
Flush();
}
///
/// Flushes the current output to the log
///
void Flush()
{
string output = Message;
if (!String.IsNullOrEmpty(Progress))
{
output += $" {Progress}";
}
if (!String.Equals(output, _lastOutput, StringComparison.Ordinal))
{
_logger.LogInformation("{Progress}", output);
_lastOutput = output;
}
}
}
///
/// Begins a new progress scope
///
/// The logger being written to
/// The message prefix
/// Scope object, which should be disposed when finished
public static ILoggerProgress BeginProgressScope(this ILogger logger, string message)
{
return new LoggerProgress(logger, message);
}
}
}