Последовательное логирование в отдельном потоке

Последовательное логирование в отдельном потоке
Atom
17.02.2013
VassilSanych


Ещё одна доработка исходников: Разгрузка основного потока от логирования. Возможность изоляции от системных ресурсов, связанных с логированием. [SPOILER][code=csharp]public abstract class BaseLogReceiver : BaseLogSource, ILogReceiver { ///

/// Инициализировать . /// protected BaseLogReceiver()

	void ILogReceiver.AddLog(LogMessage message)
	{
		LoggingQueue.AddLogAction(()=>RaiseLog(message));
	}
}


/// <summary>
///  Логирование в отдельном параллельном потоке
/// </summary>
public class LoggingQueue
{
	//если понадобится подменять реализацию
	public static LoggingQueue Instance { get; set; }


	static LoggingQueue()
	{
		Instance = new LoggingQueue();
	}


	public LoggingQueue()
	{
		StartThread();
	}


	/// <summary>
	///  Запуск отдельного параллельного потока логирования
	/// </summary>
	protected virtual void StartThread()
	{
		_loggingQueue = new ConcurrentQueue<Action>();
		_waitLog = new AutoResetEvent(false);
		Task.Run(() => DoLoggingListen());
	}


	private ConcurrentQueue<Action> _loggingQueue;
	private AutoResetEvent _waitLog;


	/// <summary>
	///		Добавление записи в лог
	/// </summary>
	/// <param name="action"></param>
	public static void AddLogAction(Action action)
	{
		Instance.AddAction(action);
	}


	/// <summary>
	///  Добавление действия записи в лог в очередь потока логирования
	/// </summary>
	/// <param name="action"></param>
	public virtual void AddAction(Action action)
	{
		_loggingQueue.Enqueue(action);
		_waitLog.Set();
	}


	/// <summary>
	///  Чтение очереди действий логирования
	/// </summary>
	protected virtual void DoLoggingListen()
	{
		do
		{
			Action logAction;
			if (_loggingQueue.TryDequeue(out logAction))
				logAction.Invoke();
			else
				_waitLog.WaitOne();
		} while (!_stopped);
	}

	private bool _stopped;
	/// <summary>
	///  Создание условий окончания работы прослушивания очереди
	/// </summary>
	public virtual void Stop()
	{
		_stopped = true;
		_waitLog.Set();
	}

}


/// <summary>
///  Затычка логирования (может понадобиться для тестирования)
/// </summary>
public class LoggingQueueMock: LoggingQueue
{
	//protected override void DoLoggingListen()
	//{
	//}

	public override void AddAction(Action action)
	{
	}

	protected override void StartThread()
	{
	}
}

[/code][/SPOILER] Кстати, можно что-то придумать и для затыкания LoggingHelper.Now. Потому что привязка кода к ресурсам системного времени - это совсем не TDD.

Критика просто жизненно необходима :)

PS Беда какая-то с описанием темы. Ломается.


Теги:


Спасибо:


1 2  >
Mikhail Sukhov

Фотография
Дата: 17.02.2013
Ответить


[quote=VassilSanych;24071]Критика просто жизненно необходима :)[/quote]

Начнем с того, что обычно формулируют проблему (типа как перед чтением стихов произносят название произведения и автора). Как решалась проблема?

Для примера. Я выделял логирование в отдельный поток, чтобы разгрузить основной поток торговли. Была проблема с перформансом логирования в файл, была решена с помощью параллельного потока.

Спасибо:

VassilSanych

Фотография
Дата: 17.02.2013
Ответить


Логирование включает файловые и другие системные операции. Это в любом случае замедляет выполнение основных алгоритмов. При том, что логирование - операция как раз совершенно не критичная к времени запуска, в отличие от торговых операций. Это не решение проблемы, это - архитектурная плюшка (о чём и сказано в комментарии темы). PS Должно было быть указано, но почему-то не было. Исправил :)

Спасибо:

ra81

Фотография
Дата: 17.02.2013
Ответить


Да и вообще была проблема того что блокирование потока логов приводило к блокированию всей системы. :). С такой плюшкой думаю сего не повторится.

Спасибо:

Mikhail Sukhov

Фотография
Дата: 17.02.2013
Ответить


[quote=VassilSanych;24075]Логирование включает файловые и другие системные операции. Это в любом случае замедляет выполнение основных алгоритмов. При том, что логирование - операция как раз совершенно не критичная к времени запуска, в отличие от торговых операций. Это не решение проблемы, это - архитектурная плюшка (о чём и сказано в комментарии темы). PS Должно было быть указано, но почему-то не было. Исправил :)[/quote]

Так ведь сейчас уже в 4.1 логирование отделено от основного потока.

Спасибо:

VassilSanych

Фотография
Дата: 17.02.2013
Ответить


[quote=Mikhail Sukhov;24083]Так ведь сейчас уже в 4.1 логирование отделено от основного потока.[/quote] Где? Я не нашёл.

Спасибо:

Mikhail Sukhov

Фотография
Дата: 17.02.2013
Ответить


[quote=VassilSanych;24084][quote=Mikhail Sukhov;24083]Так ведь сейчас уже в 4.1 логирование отделено от основного потока.[/quote] Где? Я не нашёл.

[/quote]

LogManager.cs Это к слову о важности взаимодействия.

Спасибо:

VassilSanych

Фотография
Дата: 17.02.2013
Ответить


Ага. Понял. Пишет пачками по таймеру (вспомнил, почему у меня пропадало сообщение о завершении работы). И всё-таки лочит основной поток при добавлении сообщения в список. Очередь была бы производительнее.

Спасибо:

VassilSanych

Фотография
Дата: 18.02.2013
Ответить


Кстати. У LogManager есть такой косяк: когда количество сообщений превышает заданный максимум (т.е. как раз когда система очень сильно нагружена), логирование запускается в потоке вызова.

LogManager.cs 5 KB (545)
Спасибо:

VassilSanych

Фотография
Дата: 18.02.2013
Ответить


Изменил буфер сообщений на конкурентную очередь, убрал все локи, принудительный запуск логирования заменил перещёлкиванием таймера. Последнее исправление не тестировал.

Спасибо:

pyhta4og

Фотография
Дата: 18.02.2013
Ответить


[quote=VassilSanych;24100]Кстати. У LogManager есть такой косяк: когда количество сообщений превышает заданный максимум (т.е. как раз когда система очень сильно нагружена), логирование запускается в потоке вызова. [/quote]

Это было сделано для того, чтобы очередь не отжирала всю память.

Помимо этого есть режим MaxMessages=-1 когда логирование идет синхронно. Это сделано для того чтобы производить отладку. Иначе получится что вы уже на бреакпойнт в коде робота встали, а логи еще в файл не записались.

Спасибо:
1 2  >

Добавить файлы через драг-н-дроп, , или вставить из буфера обмена.

loading
clippy