Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
Топик располагается на нескольких страницах: 1 2 3 4 5 6 7 8 9 10 11      [все]
 Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Приветствую!

4 года не был на сайте.

Хочу порекламировать свой Опер Сорс.
Если запрещено - сливайте плиз.

Итак, я тут замутил не много ни мало целый опен сорс фонд.
За пару лет был разработан целый стек новых инструментов, и один из них хочу представить сегодня Вам.

Slf4j логгер «Бобина».

Отличается:
- адской скоростью и маленьким потреблением памяти
- легкой и простой настройкой (в отличии от невменяемых настроек других логгеров)
- умеет писать одновременно сотни лог файлов
- легко (настраивается) пишет отдельные логи на каждый поток

Также работает отлично со Спрингом.

Есть полная документация на него в Вики.

https://github.com/INFINITE-TECHNOLOGY/BOBBIN

Надеюсь он вам понравится и станет основным логгером для вас.
Лично мне он нравится намного больше logback и log4j2...
3 авг 19, 02:01    [21941068]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3258
dakeiras
Slf4j логгер «Бобина».

Отличается:
- адской скоростью и маленьким потреблением памяти
- легкой и простой настройкой (в отличии от невменяемых настроек других логгеров)
- умеет писать одновременно сотни лог файлов
- легко (настраивается) пишет отдельные логи на каждый поток
Нужно срочно заявку подавать на включение в реестр российского ПО...

BobbinScriptEngine.groovy
    SimpleDateFormat dateFormat = new SimpleDateFormat(getDateFormat())

...

    String getDate() {
        return dateFormat.format(new Date())
    }



Не смущает что SimpleDateFormat нифига не потокобезопасный?


FileDestination.groovy
    BobbinFile currentBobbinFile
....

    @Override
    protected void store(String finalOutputMessageText, Level level, String className, String date) {
        String newFileName = bobbinScriptEngine.evalFileName(level.value(), className, date)
        refreshCurrentFile(newFileName)
        currentBobbinFile.writer.write(finalOutputMessageText)
        currentBobbinFile.writer.flush()
    }

    void refreshCurrentFile(String newFileName) {
        if (currentBobbinFile == null) {
            currentBobbinFile = initFile(newFileName)
        } else {
            if (currentBobbinFile.fileName != newFileName) {
                currentBobbinFile = initFile(newFileName)
            }
        }
    }

    BobbinFile initFile(String fileName) {
        BobbinFile file = new BobbinFile(fileName)
        file.fileName = fileName
        file.getParentFile().mkdirs()
        file.writer = new FileWriter(file, true)
        return file
    }



Если на время забыть, что файловые дескрипторы утекают в неизвестном направлении, этот код потокобезопасный или нет? не будет такого что логи пишутся куда-то не туда?
4 авг 19, 05:17    [21941436]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Привет Андрей!

Спасибо что посмотрел этот логгер и прокомментировал.

Я уже начал сдаваться, кажется что никому такие вещи не интересны.
А ведь объективно существующие логгеры это каменный век. Это как использовать в Порше (Spring) сиденья от лады.

Насчёт твоего комметария - simpledateformat только «parse» не потокобезопасный.
Format потокобезопасный в нём, так что норм.

Оно оттестированно на потокобезопасность и довольно давно используется у меня, так что какие-то баги очень маловероятны там.

Этот логгер в первую очередь ориентирован на многопоточные среды с сотнями одновременных потоков. Всё продуманно и проверенно много раз. За каждой кажущейся простотой здесь всегда стоит рефакторинг.


автор
Нужно срочно заявку подавать на включение в реестр российского ПО...

Я хотел принять в этом участие (только в ОАЭ), но немного опоздал с million arab coders initiative :)
4 авг 19, 12:32    [21941508]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3258
dakeiras
Насчёт твоего комметария - simpledateformat только «parse» не потокобезопасный.
Format потокобезопасный в нём, так что норм.

как-то с трудом верится...

    // Called from Format after creating a FieldDelegate
    private StringBuffer format(Date date, StringBuffer toAppendTo,
                                FieldDelegate delegate) {
        // Convert input date to time field list
        calendar.setTime(date);

    /**
     * Private member function that does the real date/time formatting.
     */
    private void subFormat(int patternCharIndex, int count,
                           FieldDelegate delegate, StringBuffer buffer,
                           boolean useDateFormatSymbols)
    {
        int     maxIntCount = Integer.MAX_VALUE;
        String  current = null;
        int     beginOffset = buffer.length();

        int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
        int value;
        if (field == CalendarBuilder.WEEK_YEAR) {
            if (calendar.isWeekDateSupported()) {
                value = calendar.getWeekYear();
            } else {
                // use calendar year 'y' instead
                patternCharIndex = PATTERN_YEAR;
                field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
                value = calendar.get(field);
            }
        } else if (field == CalendarBuilder.ISO_DAY_OF_WEEK) {
            value = CalendarBuilder.toISODayOfWeek(calendar.get(Calendar.DAY_OF_WEEK));
        } else {
            value = calendar.get(field);
        }


dakeiras
Оно оттестированно на потокобезопасность и довольно давно используется у меня, так что какие-то баги очень маловероятны там.

Этот логгер в первую очередь ориентирован на многопоточные среды с сотнями одновременных потоков. Всё продуманно и проверенно много раз. За каждой кажущейся простотой здесь всегда стоит рефакторинг.


Ну баги видны невооруженным взглядом, то что у вы "не видите" не означает что их нет. Сначала неплохо было бы довести до безошибочной работы, а потом сравнивать производительность.
4 авг 19, 13:12    [21941513]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Дмитрий Мух
Member

Откуда: Зеленоград
Сообщений: 1893
dakeiras
А ведь объективно существующие логгеры это каменный век. Это как использовать в Порше (Spring) сиденья от лады.

Так то можно утверждать, что объективно логгеры вообще не нужны. Достаточно stdout и stderr.
4 авг 19, 13:25    [21941518]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Андрей,

Я вижу что люди с трудом верят Гитхабу (новым проектам), но охотно верят помойке Stackoverflow.

Всё это проверялось и оттачивалось несколько лет, а сам логгер концептуально ведёт историю около 10ти лет.
Это наукоёмкая разработка на самом деле, и инновационная.

Но к сути дела.. SimpleDateFormat.format потокобезопасный. Вот тест:

import java.text.SimpleDateFormat

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS")
Thread.start {
for (i in 1..10000) {
System.out.println("Thread 1: " + simpleDateFormat.format(new Date()))
}
}
Thread.start {
for (i in 1..10000) {
System.out.println("Thread 2: " + simpleDateFormat.format(new Date()))
}
}


Далее - за каждый найденный баг я плачу 20$ (максимум 100$ общая сумма на всех - т.е. 5 багов, я всё таки не рокфеллер).
Я знаю только 1 маленький баг с выводом в stdout вместо stderr - но он не влияет ни на что на самом деле.

Пользуйтесь этим логгерром, надеюсь он понравится Вам больше чем старьё то что есть.

автор
Так то можно утверждать, что объективно логгеры вообще не нужны. Достаточно stdout и stderr.

Не совсем согласен. Нужно слишком много доп. параметров вручную передавать в Stdout - например время и т.д.
Код захламляется.
Но Вы не далеки от истины :)
4 авг 19, 19:28    [21941680]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Стандартный JUL был неудачен. Если-бы в тело JDK изначально была бы заложена библиотека
по уровню похожая на Log4j старых олдскульных версий 1.2.х то никакие другие логгеры
вообще нафик не впали.

По поводу мостов между slf4j и slf4j-your-fucken-impl, я бы хотел сказать что высокопроизводительный
логгер приложению вобщем-то не нужен. Потому-что главная задача приложения - делать
полезную работу. А если у вас весь смысл работы сконцетрирован в быстром логгировании и
то вы либо в TRACE mode, что само по себе - редко. Либо логгер выполняет несвойственные
ему задачи (например шлёт месседжи по JMS или Syslog). Всё это - какие-то архитектурные
просчёты и их надо обсуждать на высшем уровне а не оптимизировать кольцевые бобины и
прочие оверинжинеринги.

Если кто-то очень хочет логгированием вести учот статистики к примеру то тут есть JMX и Atomic счетчики и прочие
надстройки которые делают эти задачи эффективнее.

По поводу
- адской скоростью и маленьким потреблением памяти

Если быть дотошным - вы не управляете этой памятью. Т.к. тело месседжа всё равно формируется на прикладном
уровне. Поэтому о каком потреблении идёт речь - непонятно. Нужен какой-то тест или демо чтоб показать
что имеется в виду.
4 авг 19, 21:57    [21941721]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
Но к сути дела.. SimpleDateFormat.format потокобезопасный. Вот тест:

Дружище. Твой тест внутри содержит искусственную задержки. Это вывод на экран.
Я думаю что тебе стоит убрать этот вывод. Создать хотяб-ы 1000 потоков и проверить
гипотезу о том что содержимое ::parse() и ::format() дало взаимное тождество. И конечно
не на константе а на спектре разных дат.

Очень странно что ты не наступал на дефект SimpleDateFormat. Он действительно
был потоко-небезопасный в семерке. Его все нормальные люди оборачивали
ThreadLocal<SimpleDateFormat>.

Так что иди и проверяй очень тщательно.
4 авг 19, 22:15    [21941729]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
По поводу мостов между slf4j и slf4j-your-fucken-impl, я бы хотел сказать что высокопроизводительный
логгер приложению вобщем-то не нужен. Потому-что главная задача приложения - делать
полезную работу. А если у вас весь смысл работы сконцетрирован в быстром логгировании и
то вы либо в TRACE mode, что само по себе - редко. Либо логгер выполняет несвойственные
ему задачи (например шлёт месседжи по JMS или Syslog). Всё это - какие-то архитектурные
просчёты и их надо обсуждать на высшем уровне а не оптимизировать кольцевые бобины и
прочие оверинжинеринги.


Про Syslog это Вы в моих тредах за 2013 год прочитали?
https://www.sql.ru/forum/1028371/syslog-rfc5424

Так я собственно и сказал там что Syslog к логгеру никак не относится.

Кстати к вопросу о несвойственности - в Slf4j есть «маркеры» - бизнес функционал чистый.
В «Бобине» это конечно выключено и не поддерживается.

Насчёт производительности - к примеру у вашего заказчика клиринговый файл на 250000 записей.
И его загрузчик на определённых данных даёт неправильный расчёт, скажем задвоение комиссии.
Вы просите заказчика включить трейсы и отправить Вам на анализ.
Вот тут возникает проблема с «производительность логгера не важна».
4 авг 19, 22:51    [21941742]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
Но к сути дела.. SimpleDateFormat.format потокобезопасный. Вот тест:

Дружище. Твой тест внутри содержит искусственную задержки. Это вывод на экран.
Я думаю что тебе стоит убрать этот вывод. Создать хотяб-ы 1000 потоков и проверить
гипотезу о том что содержимое ::parse() и ::format() дало взаимное тождество. И конечно
не на константе а на спектре разных дат.

Очень странно что ты не наступал на дефект SimpleDateFormat. Он действительно
был потоко-небезопасный в семерке. Его все нормальные люди оборачивали
ThreadLocal<SimpleDateFormat>.

Так что иди и проверяй очень тщательно.

Спасибо за совет, друг.

Есть хорошие новости:

Всё проверено.
С задержками, и без, на 10000000 записей (без шуток).

SimpleDateFormat.format потокобезопасен 100%,
Вызывает проблемы “parse”.

Насчёт задержек это всё очевидные вещи. Естественно я это учёл, и делал разные тесты.
Как учёл и оптимизацию Javac и JRE - принудительно обращался к инициализированным переменным чтобы избежать пропуска неиспользуемого кода для их инициализации.

И вообще - отбросьте сомнения :) Код полностью оттестирован и отточен. Смело качайте!
4 авг 19, 22:59    [21941744]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
ThreadLocal<SimpleDateFormat>


Это всё проходилось, и даже в Бобине, и было выпилено.

На благо пользователей.

ThreadLocal негативно отображается на эффективности работы GC в контексте веб контейнера, и его нужно избегать по возможности.
4 авг 19, 23:04    [21941745]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
Стандартный JUL был неудачен. Если-бы в тело JDK изначально была бы заложена библиотека
по уровню похожая на Log4j старых олдскульных версий 1.2.х то никакие другие логгеры
вообще нафик не впали.


По какому уровню Log4j? Совершенно не индустриальная библиотека, которая по стечению обстоятельств и отсутствия альтернатив стала популярной.
У неё совершенно упоротая концепция иерархических логгеров - абсолютно не удобная привязка к уровню логирования.
Непонятно почему нельзя было изначально сделать её нормально.
4 авг 19, 23:08    [21941746]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
Если быть дотошным - вы не управляете этой памятью. Т.к. тело месседжа всё равно формируется на прикладном
уровне. Поэтому о каком потреблении идёт речь - непонятно. Нужен какой-то тест или демо чтоб показать
что имеется в виду.

это если Root логгер выключен.

Как только проходит чуть дальше сообщение - всё, логгер начинает работать и потреблять Java Heap. И тут уже начинает играть роль оптимизация логгера по потреблению памяти.
А также по обеспечению эффективности GC, т.н. memory footprint.

Я запишу видео сравнение с Logback на примере Веб приложения и выложу на этой неделе.
Спасибо, хорошая идея.
4 авг 19, 23:14    [21941747]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3258
dakeiras
Я вижу что люди с трудом верят Гитхабу (новым проектам), но охотно верят помойке Stackoverflow.

Всё это проверялось и оттачивалось несколько лет, а сам логгер концептуально ведёт историю около 10ти лет.
Это наукоёмкая разработка на самом деле, и инновационная.
А причем тут стэковерфлоу вообще? Есть код SimpleDateFormat, по коду оно в одном месте пишет в поле protected Calendar calendar, в другом месте оно ожидает прочесть записанные данные, соответственно если пишем из разных потоков, то выходит, что читаем уже мусор - это обычный code review, тут даже никакие тесты не нужны. Ну а если вы не можете правильный тест составить - это уже ваши проблемы, а не ревьювера, вот пример из https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4228335

+
import java.text.DateFormat;
import java.util.Date;

/**
 * Demonstrate that java.text.SimpleDateFormat is not thread-safe.
 *
 * @author <a href="mailto:###@###.###">Kevin J. Butler</a>
 * @version $Revision: 22$
 */
public class TestDateFormat {

	public static boolean stopping = false;

	static class Tester extends Thread {

		DateFormat dateFormat;

		Date date;

		String expected;

		int failures = 0;

		public Tester(String name, DateFormat df, Date d) {
			super(name);
			this.dateFormat = df;
			this.date = d;
			this.expected = df.format(d);
		}

		public void run() {
			while (!stopping) {
				String newText = dateFormat.format(date);
				if (!newText.equals(expected)) {
					failures++;
					System.err.println(
							Thread.currentThread() + " got " + newText +
									", expected " + expected
					);
				}
			}
		}

	}

	public static boolean testDateFormat(
			DateFormat dateFormat
	) {
		Date d1 = new Date(0);
		Date d2 = new Date();

		Tester t1 = new Tester("Tester1", dateFormat, d1);
		Tester t2 = new Tester("Tester2", dateFormat, d2);

		t1.start();
		t2.start();
		try {
			Thread.sleep(5000);
			stopping = true;
			t1.join();
			t2.join();
		} catch (InterruptedException ex) {
		}
		System.err.println("Thread1.failures = " + t1.failures +
				" Thread2.failures = " + t2.failures
		);
		return t1.failures == 0 && t2.failures == 0;
	}

	public static void main(String[] args) {
		DateFormat dateFormat = DateFormat.getDateInstance();
		System.out.println("Testing with DateFormat object");
		testDateFormat(dateFormat);
	}

}



Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Testing with DateFormat object
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/01/1970, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/01/1970, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/1970, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 01/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester2,5,main] got 01/01/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 05/08/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Thread[Tester1,5,main] got 01/01/2019, expected 01/01/1970
Thread[Tester2,5,main] got 05/08/1970, expected 05/08/2019
Exception in thread "Tester1" java.lang.ArrayIndexOutOfBoundsException: 593
at sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(BaseCalendar.java:453)
at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2397)
at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2312)
at java.util.Calendar.complete(Calendar.java:2268)
at java.util.Calendar.get(Calendar.java:1826)
at java.text.SimpleDateFormat.subFormat(SimpleDateFormat.java:1119)
at java.text.SimpleDateFormat.format(SimpleDateFormat.java:966)
at java.text.SimpleDateFormat.format(SimpleDateFormat.java:936)
at java.text.DateFormat.format(DateFormat.java:345)
at TestDateFormat$Tester.run(TestDateFormat.java:37)
Thread1.failures = 622 Thread2.failures = 873

Process finished with exit code 0


dakeiras
Далее - за каждый найденный баг я плачу 20$ (максимум 100$ общая сумма на всех - т.е. 5 багов, я всё таки не рокфеллер).
Я знаю только 1 маленький баг с выводом в stdout вместо stderr - но он не влияет ни на что на самом деле.


Перечисляйте на палку andrey.b.panfilov 60$ (там еще файловые дескрипторы текут и запись не в те файлы происходит)
5 авг 19, 06:31    [21941782]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Классический сет реализаций таких как LogBack, Log4j2 e.t.c написан на Java.

Наш Робин-Бобин написан на Groovy. И есть у меня теперь сомнения в том
что "адская скорость" имеет место.

Автор, как ты делал бенчмарк?
5 авг 19, 10:14    [21941905]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Андрей Панфилов,

Ок, хороший баг нашёл, спасибо.

andrey.b.panfilov - gmail.com?

Напиши пожалуйста детали других багов.

PS: баг с SimpleDateFormat очень маленький - там различие в 5-10 миллисикунд возникает в логе. Поэтому незаметно.
Но это не хорошо. Я поправлю.
5 авг 19, 14:42    [21942108]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
Классический сет реализаций таких как LogBack, Log4j2 e.t.c написан на Java.

Наш Робин-Бобин написан на Groovy. И есть у меня теперь сомнения в том
что "адская скорость" имеет место.

Автор, как ты делал бенчмарк?


Groovy там со статической компиляцией. Т.е. таже самая Java.
5 авг 19, 14:43    [21942109]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Андрей, в Груви файлы не надо закрывать, он сам их закрывает. Ты про это говорил?
5 авг 19, 14:57    [21942118]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton
Классический сет реализаций таких как LogBack, Log4j2 e.t.c написан на Java.

Наш Робин-Бобин написан на Groovy. И есть у меня теперь сомнения в том
что "адская скорость" имеет место.

Автор, как ты делал бенчмарк?


Groovy там со статической компиляцией. Т.е. таже самая Java.

Тоесть это и есть ответ на вопрос о бенчмарке?
5 авг 19, 15:04    [21942125]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
забыл ник
Member

Откуда:
Сообщений: 2859
dakeiras
Андрей, в Груви файлы не надо закрывать, он сам их закрывает. Ты про это говорил?

Лол, то есть все настолько плохо со знаниями? За попытку конечно 5, но тут же не лохи сидят
5 авг 19, 15:16    [21942142]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
пропущено...


Groovy там со статической компиляцией. Т.е. таже самая Java.

Тоесть это и есть ответ на вопрос о бенчмарке?


Делать бенчмарки задачи как таковой не стояло - т.к. нет задачи обосрать конкурентов (я могу высказывать своё недовольство другими библиотеками, но бенчмарком сравнивать 2 опен сорс библиотеки - это слишком).

Была задача максимально оптимизировать Бобину.

— Тестовый стенд представляет собой гибридное Spring Boot приложение, имеющее около 150 постоянных потоков, как синхронизированных, так и постоянно работающих в фоне.
Он использует JPA, Hibernate, Groovy, REST. Стенд нагружался, влючалось логирование SQL и binding в JPA/Hibernate. Ну и самое главное — стенд использовал библиотеку Blackbox, которая логирует буквально каждый expression в коде бизнес логики. Т.е. вывод примерно 25Мб/с логов. Около 400 одновременно записываемых файлов.

Дальше с Java Visual VM. Анализировалось потребление CPU и особенно памяти и эффективности GC.

Анализировались Heap Dumps, профайлер и разные статистики.

С Бобиной приложение работало ощутимо намного быстрее и меньше потребляло памяти. Конкретных замеров я не делал и не знаю, этично ли это делать лично мне как автору по отношению к другим Опен Сорс разработчикам (Logback).
5 авг 19, 15:17    [21942143]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
забыл ник,

вообще отлично. Давайте на личности переходить, оскорблять.

Это типичный современный Российский подход.
5 авг 19, 15:20    [21942149]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
забыл ник
Member

Откуда:
Сообщений: 2859
dakeiras
забыл ник,

вообще отлично. Давайте на личности переходить, оскорблять.

Это типичный современный Российский подход.

Во-первых я не из России, во-вторых мы на форуме а не на маркетинг-вечеринке, а в-третьих чрезмерная самонадеянность чревата. Одно дело вбросить свою либу и спросить - мол, как оно ребята? Другое дело оголтело втюхивать свою поделку выдавая ее за край передовой мысли.
Попытка сделать что-то новое это хорошо, тут никто и не пытается наехать. А вот то что вы понятия не имеете как писать потокобезопасный код, работать с файлами, писать тесты и мерить перфоманс то тут вы попались с головой, и что вы так удивляетесь негативному фидбэку?
5 авг 19, 15:28    [21942164]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Андрей,

Я кажется понял твою идею насчёт закрытия файлов. Можно словить too many open files, да?

Надо подумать как закрывать их оптимально, возможно сделаю настраивамый expression "isNeedToCloseFile".
Если закрывать\открывать каждый раз - это будет тормозить.

Это было осмысленное решение не закрывать их.

забыл ник,

где конкретно я попался что не умею писать потокобезопасный код?
Есть minor баг с SimpleDateFormat, который выражается тем что миллисикунды не всегда правильно в файлах пишутся.
5 авг 19, 15:48    [21942183]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
В версии 1.x файлы закрывались и архивировались:

https://github.com/INFINITE-TECHNOLOGY/BOBBIN/blob/ca0fb4d1a5966e7dbe0471be67234422f55c49bc/src/main/groovy/io/infinite/bobbin/destinations/FileDestination.groovy#L79

    static void zipAndDelete(File file) {
        final Integer BUFFER_LENGTH = 2048
        if (file.isFile()) {
            new File(file.zipFileName as String).getParentFile().mkdirs()
            FileOutputStream fileOutputStream = new FileOutputStream(file.zipFileName as String)
            ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(fileOutputStream))
            byte[] bytes = new byte[BUFFER_LENGTH]
            FileInputStream fileInputStream = new FileInputStream(file)
            BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, BUFFER_LENGTH)
            ZipEntry entry = new ZipEntry(file.getName())
            zipOutputStream.putNextEntry(entry)
            Integer countBytes
            while ((countBytes = bufferedInputStream.read(bytes, 0, BUFFER_LENGTH)) != -1) {
                zipOutputStream.write(bytes, 0, countBytes)
            }
            bufferedInputStream.close()
            zipOutputStream.close()
            file.delete()
        }
    }


Я убрал архивирование, т.к. концептуально это не задача логгера.
Наверное надо вернуть закрытие файлов, когда они точно становятся неиспользуемыми (например при смене даты).
5 авг 19, 15:53    [21942189]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras, дорогой друг. Я тебе настойчиво советую провести сравнительное тестирование
твоей бобины с любой другой имплементацией. Если та (другая имплементация) будет
медленной - приводи пример конфигов. Есть масса стероидов как ее разогнать.
Я убежден в этом.

P.S. Груви никогда не был быстрым с точки зрения runtime.
5 авг 19, 15:56    [21942192]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton,

ок сделаю, в течении 1 недели.

Насчёт Груви - это устаревшее на 10 лет инфа. С динамической компиляцией он медленней обычное Джавы, но достаточно быстр.
Со статической компиляцией - он одинаковый по скорости с Джавой (Груви код в равнозначный Джава код переводится).
5 авг 19, 16:02    [21942198]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Kachalov
Member

Откуда: Москва
Сообщений: 5642
dakeiras
Я убрал архивирование, т.к. концептуально это не задача логгера.

- не вдаваясь в детали, лично за себя скажу, что мне нравится та функциональность которая есть в Log4J - например, когда захотелось отправить логи через JMS в сборщик логов, не пришлось ничего менять в коде приложения
5 авг 19, 17:15    [21942270]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton,

ок сделаю, в течении 1 недели.

Насчёт Груви - это устаревшее на 10 лет инфа. С динамической компиляцией он медленней обычное Джавы, но достаточно быстр.
Со статической компиляцией - он одинаковый по скорости с Джавой (Груви код в равнозначный Джава код переводится).

Я попробую поднять свой бенчмарк Groovy в разрезе численных расчетов. Кажется у нас были
какие-то суровые проблемы с этим. В основном касалось не компилляции а динамической типизации.

Как они порешались сегодня - я не знаю. Но по состоянию на года 3 назад они все еще были.
5 авг 19, 17:19    [21942276]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
mayton,

ок сделаю, в течении 1 недели.

Насчёт Груви - это устаревшее на 10 лет инфа. С динамической компиляцией он медленней обычное Джавы, но достаточно быстр.
Со статической компиляцией - он одинаковый по скорости с Джавой (Груви код в равнозначный Джава код переводится).

Я попробую поднять свой бенчмарк Groovy в разрезе численных расчетов. Кажется у нас были
какие-то суровые проблемы с этим. В основном касалось не компилляции а динамической типизации.

Как они порешались сегодня - я не знаю. Но по состоянию на года 3 назад они все еще были.


Так говорю же, у меня используется Статическая Компиляция (аннотаций нет т.к. используется глобальный плагин Gradle для статической компиляции - "Groovy Enterprise Plugin") - все типы статические.
5 авг 19, 17:25    [21942286]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Kachalov
dakeiras
Я убрал архивирование, т.к. концептуально это не задача логгера.

- не вдаваясь в детали, лично за себя скажу, что мне нравится та функциональность которая есть в Log4J - например, когда захотелось отправить логи через JMS в сборщик логов, не пришлось ничего менять в коде приложения

Я-же говорю. Встроить в JDK просто одну удачную библиотечку наподобие этой - и конец всем
терзаниям и велосипедам.
5 авг 19, 17:27    [21942292]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton
пропущено...

Я попробую поднять свой бенчмарк Groovy в разрезе численных расчетов. Кажется у нас были
какие-то суровые проблемы с этим. В основном касалось не компилляции а динамической типизации.

Как они порешались сегодня - я не знаю. Но по состоянию на года 3 назад они все еще были.


Так говорю же, у меня используется Статическая Компиляция (аннотаций нет т.к. используется глобальный плагин Gradle для статической компиляции - "Groovy Enterprise Plugin") - все типы статические.

Я говорю не о компилляции. А о типизации. Я надеюсь ты понимаешь разницу?
5 авг 19, 17:28    [21942294]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Моё предложение в силе.

Андрей нашёл 1 явный баг (minor) и 1 потенциальный баг с max open files exceeded.
Жду его детали чтобы перевести $.

За каждый найденный баг перевожу 20$, макс 5 багов (100$) - в общей сложности на всех.

Насчёт потокобезопасности - после анализа Ник не найден, я вижу потокобезопасный баг с довольно редкой частотой.
Тоже minor. Готов перевести $.

Итого пока 2 minor бага (потокобезопасность), 1 потенциальный баг с закрытием файлов (мне надо это обдумать).

Теперь прошу всех отписавшихся скачать и поюзать этот логгер.
5 авг 19, 17:31    [21942298]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton,

В Груви Статическая компиляция значит Статическую Типизацию.
5 авг 19, 17:31    [21942299]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Частота записи в не те файлы 1 случай на 27500 строк.
Это в синтетическом тесте. На практике это будет - 1 на миллионы.

Пренебрежимо для логгера.

Won't fix - перформанс дороже.

Но это хороший фидбек и засчитывается как баг.
5 авг 19, 17:37    [21942302]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras, я проверю. Но мой вопрос к перформансу - по прежнему актуален.
5 авг 19, 17:37    [21942303]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
Частота записи в не те файлы 1 случай на 27500 строк.
Это в синтетическом тесте. На практике это будет - 1 на миллионы.

Пренебрежимо для логгера.

Won't fix - перформанс дороже.

Но это хороший фидбек и засчитывается как баг.

Капец... ты классный менеджер

Won't fix...
5 авг 19, 17:39    [21942310]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Kachalov
dakeiras
Я убрал архивирование, т.к. концептуально это не задача логгера.

- не вдаваясь в детали, лично за себя скажу, что мне нравится та функциональность которая есть в Log4J - например, когда захотелось отправить логи через JMS в сборщик логов, не пришлось ничего менять в коде приложения


с Logstash сейчас и так не приходится менять код. Зато работает быстрее чем JMS.
5 авг 19, 17:40    [21942313]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
Частота записи в не те файлы 1 случай на 27500 строк.
Это в синтетическом тесте. На практике это будет - 1 на миллионы.

Пренебрежимо для логгера.

Won't fix - перформанс дороже.

Но это хороший фидбек и засчитывается как баг.

Капец... ты классный менеджер

Won't fix...


Это обсуждаемо естественно.

Чтобы сделать полностью потокобезопасно - надо добавлять либо synchronized, либо ThreadLocal, либо изобретать что-то.
Первые 2 - замедляют (ThreadLocal так же плохо влияет на GC).

Вопрос - надо ли оно, если на практике почти не проявляется? Зато работает быстрее?
5 авг 19, 17:42    [21942317]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
В космос с тобой лететь нельзя...
5 авг 19, 17:50    [21942329]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton,

эту проблему нужно рассматривать в комплексе, учитывая стратегии объявления логгеров.

Сейчас индустриальная стратегия - делать поле логгера статичным в классах.
Это означает повышенную конкуренцию по сравнению с полем экземпляра класса.

А значит - частое переключение лог файла.

Я уже делал разные реализации включая LogFileManager и ThreadLocal - от всего этого GC плохеет.

Я подумаю ещё...
5 авг 19, 17:58    [21942339]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Не забудь в README.md описать чем ты там жертвуешь в пользу перформанса.
5 авг 19, 18:01    [21942343]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
забыл ник
Member

Откуда:
Сообщений: 2859
Ну быстрее всего логи просто не писать
5 авг 19, 18:06    [21942346]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Внёс изменения в соотвествии с рекомендациями уважаемых комментаторов:
- SimpleDateFormat убрал (заменил на FastDateFormat из Apache commons)
- Добавил ThreadLocal для файлов. Теперь будет потокобезопасно, и даже ещё быстрее.
- Добавил закрытие файлов

Это пока не релиз. Я несколько дней это всё погоняю на тестовых проектах.

Посмотрите коммит, есть ли ещё пожелания.

https://github.com/INFINITE-TECHNOLOGY/BOBBIN/commit/1f30913ace83cc283318bd6f77631d8f117357cd

Прошу комментаторов оставить свои детали для paypal.

Прошу всех скачать логгер и начать им пользоваться :)

Он реально очень крут, посоны...
5 авг 19, 19:56    [21942424]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
+ off

Мне вспоминается детская сказка про Толстяка который страдал каннибализмом.

Картинка с другого сайта.

Robbin, a bobbin, the big-bellied Ben,
He ate more meat than threescore men;
He ate a cow, he ate a calf,
He ate a butcher and a half;
He ate a church, he ate a steeple,
He ate the priest and all the people.

В переводе Маршака это звучало примерно так.

Робин Бобин Барабек
Скушал 40 человек...


В данном случае bobbin следовало переводить как "катушка".

Робин - толстая-катушка
Он сожрал - более 60 людей... и так далее.

Вобщем этот slf4j логгер должен ассоциироваться с ужасным канибалом который
поедает коров, священников а так-же здания и сооружения.
6 авг 19, 10:07    [21942645]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton,

Бобина это катушка, часть полётного регистратора (чёрного ящика - BlackBox - мой другой проект по автоматическому добавлению логирования в код - если интересно - расскажу о нём).

Также бобина используется для бекапов на ленту (кассета).

Ну и последнее - у меня есть проект Carburetor (AST API), Бобиной так же называют генератор в двигателях.

Так что это исключительно логичное наименование.

Вы скачали логгер?:)
6 авг 19, 11:41    [21942756]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Нет. Я сейчас хочу вернуться к своему проекту CardRaytracer и посмотреть почему Groovy-версию
трассировщика луча мы оставили в ветке экспериментальных. Возможно он не работал (это один поинт)
или работал медленно (это другой). Но после того как разберусь я смогу показать коеэффициент
перформанса между Java/Groovy на вычислительных операциях и каллбеках.

Опимизации груви я конечно включу на максимум который только будет возможен.

Если у вас есть какие-то дополнения и предложения - буду рад услышать.

P.S. Нет ваш логгер я пока не скачал. Мне непонятна его идея. По крайней мере вы ее
не раскрыли. И брать просто так логгер без идеи я не хочу. Мне это не интересно.
6 авг 19, 12:31    [21942808]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton,

Здесь не стоит вопрос быстродействия Груви.
Во первых используется Статическая компиляция, которая равнозначна Java коду (см. ниже), во вторых это не предмет этой темы.
Тех. стек исследован и проверен на быстродействие.

Если интересно ниже класс на Груви и его декомпилированная Java версия. Как видно это обычный Java код.
(Используется @CompileStatic глобально через плагин Gradle)

Groovy класс:
+
package io.infinite.bobbin.destinations

import io.infinite.bobbin.BobbinFile
import io.infinite.bobbin.Level
import io.infinite.bobbin.config.DestinationConfig
import org.slf4j.helpers.Util

class FileDestination extends Destination {

ThreadLocal<BobbinFile> bobbinFileMap = new ThreadLocal<BobbinFile>()

///////////////////CONSTRUCTOR \/\/\/\/\/\/
FileDestination(DestinationConfig destinationConfig) {
super(destinationConfig)
}
///////////////////CONSTRUCTOR /\/\/\/\/\/\

@Override
protected void store(String finalOutputMessageText, Level level, String className, String date) {
String newFileName = bobbinScriptEngine.evalFileName(level.value(), className, date)
refreshCurrentFile(newFileName)
bobbinFileMap.get().writer.write(finalOutputMessageText)
bobbinFileMap.get().writer.flush()
}

void refreshCurrentFile(String newFileName) {
if (bobbinFileMap.get() == null) {
bobbinFileMap.set(initFile(newFileName))
} else {
if (bobbinFileMap.get().fileName != newFileName) {
bobbinFileMap.get().writer.close()
bobbinFileMap.set(initFile(newFileName))
}
}
}

BobbinFile initFile(String fileName) {
BobbinFile file = new BobbinFile(fileName)
file.fileName = fileName
file.getParentFile().mkdirs()
file.writer = new FileWriter(file, true)
return file
}

static {
Util.report("Bobbin: " + Thread.currentThread().getName().padRight(16) + ": " + "application working dir: " + new BobbinFile("./").getCanonicalPath())
}

}


Он же декомпилирован (Java код):
+
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package io.infinite.bobbin.destinations;

import groovy.transform.Generated;
import io.infinite.bobbin.BobbinFile;
import io.infinite.bobbin.Level;
import io.infinite.bobbin.config.DestinationConfig;
import java.io.FileWriter;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.StringGroovyMethods;
import org.slf4j.helpers.Util;

public class FileDestination extends Destination {
private ThreadLocal<BobbinFile> bobbinFileMap;

public FileDestination(DestinationConfig destinationConfig) {
super(destinationConfig);
ThreadLocal var2 = new ThreadLocal();
this.bobbinFileMap = var2;
}

protected void store(String finalOutputMessageText, Level level, String className, String date) {
String newFileName = ((FileDestination)this).getBobbinScriptEngine().evalFileName(level.value(), className, date);
this.refreshCurrentFile(newFileName);
Object var10000 = null;
((FileWriter)((BobbinFile)this.bobbinFileMap.get()).getWriter()).write(finalOutputMessageText);
var10000 = null;
((FileWriter)((BobbinFile)this.bobbinFileMap.get()).getWriter()).flush();
var10000 = null;
}

public void refreshCurrentFile(String newFileName) {
Object var10000;
if (this.bobbinFileMap.get() == null) {
this.bobbinFileMap.set(this.initFile(newFileName));
var10000 = null;
} else if (ScriptBytecodeAdapter.compareNotEqual(((BobbinFile)this.bobbinFileMap.get()).getFileName(), newFileName)) {
((FileWriter)((BobbinFile)this.bobbinFileMap.get()).getWriter()).close();
var10000 = null;
this.bobbinFileMap.set(this.initFile(newFileName));
var10000 = null;
}

}

public BobbinFile initFile(String fileName) {
BobbinFile file = new BobbinFile(fileName);
file.setFileName(fileName);
Object var10001 = null;
((BobbinFile)file).getParentFile().mkdirs();
FileWriter var4 = new FileWriter(file, true);
file.setWriter(var4);
var10001 = null;
return file;
}

static {
Util.report(StringGroovyMethods.plus(StringGroovyMethods.plus(StringGroovyMethods.plus(StringGroovyMethods.plus("Bobbin: ", StringGroovyMethods.padRight(Thread.currentThread().getName(), 16)), ": "), "application working dir: "), ((BobbinFile)(new BobbinFile("./"))).getCanonicalPath()));
Object var10000 = null;
}

@Generated
public ThreadLocal<BobbinFile> getBobbinFileMap() {
return this.bobbinFileMap;
}

@Generated
public void setBobbinFileMap(ThreadLocal<BobbinFile> var1) {
this.bobbinFileMap = var1;
}
}


Касательно идеи - вот это отличный вопрос.

Идея очень простая - использовать нативные булевские выражения на Java/Groovy для настройки уровня логирования и классов.
Например:
"levels": "['debug', 'info', 'warn', 'error'].contains(level)"

"classes": "className.contains('conf.plugins.input')"


И тоже самое для форматирования:
"format": "level.toUpperCase() + ' [' + threadName + '] ' + dateTime + ': ' + message + '\\n'"


Круто, да? Не нужен никакой чудо-синтаксис форматирования Log4j.
Не нужна чудо-концепция иерархических логгеров.

И ещё: имя файла также настраивается:
"fileName": "\"./LOGS/THREADS/${threadGroupName}/${threadName}/${level}/${threadName}_${level}_${date}.log\"

Как видно, оно содержит ${threadName} - и другие переменные - вот так лёгким движением руки ОДНА настройка отвечает за создание МНОГИХ файлов.
6 авг 19, 13:17    [21942861]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Alexey Tomin
Member

Откуда: Самара
Сообщений: 1733
dakeiras
Groovy класс:


Я вот всё никак не мог дойти почитать код. Что-то меня останавливало.
То ли то, что автор оценивает умных людей как идиотов, даже не разоравшись.
То ли что не понимает, что документацию пишуют чтобы читать, а не чтобы высокомерно отвергать.
Но тут понял- человек, неспособный вставить исходник как код- точно не может написать ничего интересного.
6 авг 19, 13:24    [21942880]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
Идея очень простая - использовать нативные булевские выражения на Java/Groovy для настройки уровня логирования и классов.

А если мне на ходу надо включить TRACE? Без остановки приложения.
6 авг 19, 13:31    [21942891]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Alexey Tomin,

Где я кого-то высокомерно оценивал? Можно пример или цитату мою?

Я вставил под кат чтобы конкретно Mayton прочитал, и не захламлять тему.

В том же сообщении исходники вставлены как код.

В данном случае (как и в нескольких других в этой теме от других комментаторов) вы переходите на личности, зачем-то подразумеваете мою тупость и пр.

Можно пожалуйста перестать это делать, и обсуждать вопросы по теме?

автор
То ли что не понимает, что документацию пишуют чтобы читать, а не чтобы высокомерно отвергать.

Не совсем понял, вы про какую документацию? Есть Вики, там довольно детально всё описано.
Никто ничего не отвергает.
6 авг 19, 13:32    [21942894]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
Идея очень простая - использовать нативные булевские выражения на Java/Groovy для настройки уровня логирования и классов.

А если мне на ходу надо включить TRACE? Без остановки приложения.


Это опасненько. В Бобине не поддерживается такое сейчас.
Можно обсудить - надо ли такое поддерживать.
6 авг 19, 13:33    [21942901]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton
пропущено...

А если мне на ходу надо включить TRACE? Без остановки приложения.


Это опасненько. В Бобине не поддерживается такое сейчас.
Можно обсудить - надо ли такое поддерживать.

Стоп-стоп. Родной. Ты о чем?

Это не надо обсуждать. Это надо просто вынести в самый главный поинт. Библиотека логгирования
такая как Log4j например поддерживает смену режима на ходу персонально для каждого логгера.
И еще дает много чего для аппендеров. В принципе имеет конроль над runtime.

И если твоя это не поддерживает то ее можно сразу выкидывать на свалку.

Даже не скачивая.

Ферштейн?
6 авг 19, 13:44    [21942921]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
пропущено...


Это опасненько. В Бобине не поддерживается такое сейчас.
Можно обсудить - надо ли такое поддерживать.

Стоп-стоп. Родной. Ты о чем?

Это не надо обсуждать. Это надо просто вынести в самый главный поинт. Библиотека логгирования
такая как Log4j например поддерживает смену режима на ходу персонально для каждого логгера.
И еще дает много чего для аппендеров. В принципе имеет конроль над runtime.

И если твоя это не поддерживает то ее можно сразу выкидывать на свалку.

Даже не скачивая.

Ферштейн?


Log4j не поддерживает перенастройку в рантайме.
https://stackoverflow.com/questions/4598702/dynamically-changing-log4j-log-level

Либо нужно код подгонять, либо JMS, либо небезопасный в веб приложениях configureAndWatch опять же требующий модификацию в коде.

Это нельзя назвать поддержкой.

Так что повторю вопрос: вы правда пользуетесь этим функционалом? У вас он интегрирован? (а он требует интеграции в код)
Если да, то можно дальше подумать над его добавлением, спросить других участников.
6 авг 19, 13:57    [21942937]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
забыл ник
Member

Откуда:
Сообщений: 2859
dakeiras
mayton
пропущено...

Стоп-стоп. Родной. Ты о чем?

Это не надо обсуждать. Это надо просто вынести в самый главный поинт. Библиотека логгирования
такая как Log4j например поддерживает смену режима на ходу персонально для каждого логгера.
И еще дает много чего для аппендеров. В принципе имеет конроль над runtime.

И если твоя это не поддерживает то ее можно сразу выкидывать на свалку.

Даже не скачивая.

Ферштейн?


Log4j не поддерживает перенастройку в рантайме.
https://stackoverflow.com/questions/4598702/dynamically-changing-log4j-log-level

Либо нужно код подгонять, либо JMS, либо небезопасный в веб приложениях configureAndWatch опять же требующий модификацию в коде.

Это нельзя назвать поддержкой.

Так что повторю вопрос: вы правда пользуетесь этим функционалом? У вас он интегрирован? (а он требует интеграции в код)
Если да, то можно дальше подумать над его добавлением, спросить других участников.


Ну налету конечно не так часто пользуются. Но в нормальной организации тебе никто не даст залить новые артифакты для того чтобы поменять уровень трассировки логов. А вот поменять log4j-конфиг вполне себе можно. И это как сказал mayton - основополагающая штука для любого логера. Или ты думал что все такие тупые а ты один Д'Артаньян?
6 авг 19, 14:03    [21942947]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton
пропущено...

Стоп-стоп. Родной. Ты о чем?

Это не надо обсуждать. Это надо просто вынести в самый главный поинт. Библиотека логгирования
такая как Log4j например поддерживает смену режима на ходу персонально для каждого логгера.
И еще дает много чего для аппендеров. В принципе имеет конроль над runtime.

И если твоя это не поддерживает то ее можно сразу выкидывать на свалку.

Даже не скачивая.

Ферштейн?


Log4j не поддерживает перенастройку в рантайме.
https://stackoverflow.com/questions/4598702/dynamically-changing-log4j-log-level

Либо нужно код подгонять, либо JMS, либо небезопасный в веб приложениях configureAndWatch опять же требующий модификацию в коде.

Это нельзя назвать поддержкой.

Так что повторю вопрос: вы правда пользуетесь этим функционалом? У вас он интегрирован? (а он требует интеграции в код)
Если да, то можно дальше подумать над его добавлением, спросить других участников.

На прошлом проекте - пользовался и очень даже. Включал и выключал логгеры и аппендеры.

Что там потоконебезопасно? Приведи пример почему это нельзя.
6 авг 19, 14:04    [21942948]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
забыл ник
dakeiras
пропущено...


Log4j не поддерживает перенастройку в рантайме.
https://stackoverflow.com/questions/4598702/dynamically-changing-log4j-log-level

Либо нужно код подгонять, либо JMS, либо небезопасный в веб приложениях configureAndWatch опять же требующий модификацию в коде.

Это нельзя назвать поддержкой.

Так что повторю вопрос: вы правда пользуетесь этим функционалом? У вас он интегрирован? (а он требует интеграции в код)
Если да, то можно дальше подумать над его добавлением, спросить других участников.


Ну налету конечно не так часто пользуются. Но в нормальной организации тебе никто не даст залить новые артифакты для того чтобы поменять уровень трассировки логов. А вот поменять log4j-конфиг вполне себе можно. И это как сказал mayton - основополагающая штука для любого логера. Или ты думал что все такие тупые а ты один Д'Артаньян?


Я не понимаю, вы про какие артефакты? Точно также меняется Bobbin.json конфиг.
И ещё раз прошу - пожалуйста не переходите на личности.
Это последнее предупреждение, если ещё раз увижу оскорбительные комментарии - я уйду из этой темы\сайта.
6 авг 19, 14:10    [21942953]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
На прошлом проекте - пользовался и очень даже. Включал и выключал логгеры и аппендеры.

Что там потоконебезопасно? Приведи пример почему это нельзя.


Оки, давай обсудим эту фичу. Если нужная фича - добавим, без проблем.

Не, не потоконебезопасно - просто опасно - криворукий админ врубит на продакшене трейсы - и продакшен рухнет.

В твоём случае - перезапустить приложение было затруднительно? Нужно было именно в рантайме?
6 авг 19, 14:14    [21942955]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
автор
На прошлом проекте - пользовался и очень даже. Включал и выключал логгеры и аппендеры.

Что там потоконебезопасно? Приведи пример почему это нельзя.


Оки, давай обсудим эту фичу. Если нужная фича - добавим, без проблем.

Не, не потоконебезопасно - просто опасно - криворукий админ врубит на продакшене трейсы - и продакшен рухнет.

В твоём случае - перезапустить приложение было затруднительно? Нужно было именно в рантайме?

Нет-нет. Нечего обсуждать. Добавляй сразу.

В моем случае перезапускать биржевое приложение было дорого. Стоит денег. Понимаешь?
Кроме того это не приложение а целый грид из полу-сотни узлов.

По поводу потоконебезопасно. Мне очень приятно конечно что ты так заботишся о потокобезопасности.
Тем более что страницу назад тебя группа людей убеждала в том что календарь небезопасен.
По этому поводу - не переживай. Log4j1.2.x - библиотечка промышленного уровня. Она давно
оттестирована и работает эталонно надёжно. Те странные юзкейсы которые ты нарисовал - я не понял.
Что там упадёт от включение TRACE - непонятно. Будь пожалуйта более конкретным.
6 авг 19, 14:18    [21942960]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton,

Оки, добавим эту фичу, спасибо.

Теперь встаёт вопрос - как это лучше всего сделать.

Через условный "FileWatchService" (т.е. через файл Bobbin.json с настройками логгера на дисковой системе) - или как-то иначе?
Я держу в голове сейчас use cases с микросервисами - в облаке невозможно будет полезть файл на диске поменять.

Как вариант - можно подготовить апишку в логгере, а конечное приложение при желании может её как Веб-сервис опубликовать.
(но даже тут - это сработает только на одном ноде).
6 авг 19, 14:25    [21942972]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Не с того края зашел. Ты сначала разработай runtime. Тоесть чтобы это концептуально было и работало.

А как конфигурить - это вопрос не этого форума. Как хочешь. Хоть json, хоть ямл. Хоть JMX.
6 авг 19, 14:59    [21943005]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
Не с того края зашел. Ты сначала разработай runtime. Тоесть чтобы это концептуально было и работало.

А как конфигурить - это вопрос не этого форума. Как хочешь. Хоть json, хоть ямл. Хоть JMX.


Ок, согласен. Посижу подумаю.
Скорее всего это будет API для опубликования его как Веб сервис через админский endpoint в конечном приложении.

Bobbin Configuration REST Web Service Format.

И он собственно будет принимать такой же формат как в Bobbin.json.

(Для других читателей - здесь речь именно о runtime конфигурации без перезапуска приложения. Изначальная инициализация осуществляется через Bobbin.json - файл с настройками логгера - он конечно изначально поддерживается и вокруг него собственно логгер и построен).



О прочем: я погонял изменения по комментам из этой темы на тестовых стендах (помимо testng тестов). Всё ок.
Обуликовал релиз:

<dependency>
  <groupId>io.infinite</groupId>
  <artifactId>bobbin</artifactId>
  <version>2.0.5</version>
</dependency>


compile 'io.infinite:bobbin:2.0.4'
6 авг 19, 15:19    [21943027]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Поправочка:

compile 'io.infinite:bobbin:2.0.5'
6 авг 19, 15:21    [21943028]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 9224
dakeiras
Log4j не поддерживает перенастройку в рантайме.
https://stackoverflow.com/questions/4598702/dynamically-changing-log4j-log-level
Делая далеко идущие утверждения, было бы не худо ссылаться на документацию. Ну или, хотя бы, внимательно читать ответы SO по вашей же ссылке.
Настройки Log4j 1.2 меняются схожим образом. Для xml-конфигурации - точно работает.
Да, у Log4j 1.2 может терять сообщения при такой переконфигурации, но это - другая проблема.
6 авг 19, 16:45    [21943102]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Basil A. Sidorov,

Обсуждался конкретно Log4j.

Log4j2 это совершенно другой проект.

По ссылке Stackoverflow выше касательно Log4j:

автор
Caution: configureAndWatch method is unsafe for use in J2EE environments due to a Thread leak


Можно пример как это настраивается в Log4j без изменения пользовательского кода?

PS: необязательно в каждом сообщении делать присказки типа "далекоидущие выводы" и пр., это касается всех комментаторов.
Вы не профессора, а я не студент на дипломном проекте.
Однозначно одно - у меня достаточно опыта признавать свои ошибки и понимать что мои знания сильно ограничены.
Что не мешает мне создавать охуенные проекты, полезные для всех.
6 авг 19, 16:57    [21943118]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
Что не мешает мне создавать охуенные проекты, полезные для всех.

Что за проекты? Сколько их? И из какой предметной области?
6 авг 19, 17:10    [21943131]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton,

В основном инфраструктура:
- автоматизация кода, логирование, профилирование, безопасность (аутентификация, авторизация) - для микросервисов\облака.

Есть прикладной проект Pigeon - он в первую очередь для банков.

https://i-t.io/
https://github.com/INFINITE-TECHNOLOGY/
6 авг 19, 17:24    [21943145]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras
Pigeon


А можно уточнить для каких это целей применяется?
Мельком посмотрел - для отправки сообщения каждый раз пересоздается URLConnection. (А обертка для него aka SenderDefault каждый раз пересоздается через рефлексию).
6 авг 19, 17:37    [21943160]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
СЗОТ

Pigeon:

SenderDefaultHttpsUnsecure#sendHttpMessage при отправке каждого сообщения создает новый SSLContext и меняет HttpsURLConnection.setDefaultSSLSocketFactory

Это "охуенно" ?
6 авг 19, 17:42    [21943164]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
dakeiras
Pigeon


А можно уточнить для каких это целей применяется?
Мельком посмотрел - для отправки сообщения каждый раз пересоздается URLConnection. (А обертка для него aka SenderDefault каждый раз пересоздается через рефлексию).


Посылать OTP через SMS гейтвей либо Transaction (покупки) Push Notifications (SOAP, JSON) на внешний хост.
6 авг 19, 17:58    [21943173]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
СЗОТ

Pigeon:

SenderDefaultHttpsUnsecure#sendHttpMessage при отправке каждого сообщения создает новый SSLContext и меняет HttpsURLConnection.setDefaultSSLSocketFactory

Это "охуенно" ?


Можно чуть больше деталей, в чём Вы видите проблему. Я буду рад исправить. Это кстати скоро идёт на продакшен после 8 месячного тестирования.
6 авг 19, 18:00    [21943174]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton,

В основном инфраструктура:
- автоматизация кода, логирование, профилирование, безопасность (аутентификация, авторизация) - для микросервисов\облака.

Есть прикладной проект Pigeon - он в первую очередь для банков.

https://i-t.io/
https://github.com/INFINITE-TECHNOLOGY/

Non-commercial open-source software organization?

А как вы зарабатываете? Вы альтруисты?
6 авг 19, 18:07    [21943179]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras,

1) Зачем каждый раз пересоздавать SslContext?
2) Зачем использовать глобальные настройки SslSocketFactory? (Любой другой код, соседствующий с этой библиотекой и использующий HttpsUrlConnection может вести себя неожидано)
3) Зачем каждый раз пересоздавать обертку для отправки запросов?
6 авг 19, 18:09    [21943181]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras,

if (httpRequest.method == "POST") { <-- я понимаю, что это работает, так как "POST" интернируется, но почему не equals?
6 авг 19, 18:11    [21943184]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
mayton,

В основном инфраструктура:
- автоматизация кода, логирование, профилирование, безопасность (аутентификация, авторизация) - для микросервисов\облака.

Есть прикладной проект Pigeon - он в первую очередь для банков.

https://i-t.io/
https://github.com/INFINITE-TECHNOLOGY/

Non-commercial open-source software organization?

А как вы зарабатываете? Вы альтруисты?

На грантах правительственных сидим. :)

На самом деле там 1 человек я пока. Никак не зарабатываем, даже донатим бабло на другой опенсорс.
Бабло с зарплаты своей, работаю на другой фирме я.

Когда-нибудь если что-то станет популярным, появятся и другие контрибьюторы\мейнтейнеры.
6 авг 19, 18:13    [21943187]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
Последний вопрос не в кассу, это же groovy.
6 авг 19, 18:14    [21943188]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
dakeiras,

if (httpRequest.method == "POST") { <-- я понимаю, что это работает, так как "POST" интернируется, но почему не equals?


Груви код, там надо == писать. По умолчанию == в Груви это equals.

http://docs.groovy-lang.org/latest/html/documentation/core-operators.html#_identity_operator
6 авг 19, 18:15    [21943189]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras
Lelouch
dakeiras,

if (httpRequest.method == "POST") { <-- я понимаю, что это работает, так как "POST" интернируется, но почему не equals?


Груви код, там надо == писать. По умолчанию == в Груви это equals.

http://docs.groovy-lang.org/latest/html/documentation/core-operators.html#_identity_operator


да, я уже понял, постом выше.

application.config стоит поправить:
pigeonConfFile=C:/Users/anton.pryamostanov/IdeaProjects/PIGEON_PLUGINS/src/conf/Pigeon.json
pigeonOutPluginsDir=C:/Users/anton.pryamostanov/IdeaProjects/PIGEON_PLUGINS/src/conf/plugins/output
pigeonInputPluginsRestDir=C:/Users/anton.pryamostanov/IdeaProjects/PIGEON_PLUGINS/src/conf/plugins/input/rest
pigeonInputPluginsHttpDir=C:/Users/anton.pryamostanov/IdeaProjects/PIGEON_PLUGINS/src/conf/plugins/input/http
6 авг 19, 18:17    [21943191]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
dakeiras,

1) Зачем каждый раз пересоздавать SslContext?
2) Зачем использовать глобальные настройки SslSocketFactory? (Любой другой код, соседствующий с этой библиотекой и использующий HttpsUrlConnection может вести себя неожидано)
3) Зачем каждый раз пересоздавать обертку для отправки запросов?


По вопросу №1 - SSLContext.getInstance("TLS") - это разве не Singletone?
Без шуток, если честно особо не глядел.

Если нет, поправлю. Не надо так делать.

По вопросу №2 - это standalone приложение, оно не подразумевает размещение на общем сервере приложений с другими.
Именно по причине глобалього defaultSSLSocketFactory.

Какие есть альтернативы setDefaultSSLSocketFactory?

По вопросу №3 - это отлично подмеченно. Поправлю.
6 авг 19, 18:20    [21943194]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Прошу учитывать, что Pigeon это пред-релизное состояние, RC.
99.99% готовность, в течении нескольких недель будет релиз.
6 авг 19, 18:21    [21943195]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
А чё в вашем ПИНГВИНЕ нулевое тестовое покрытие? Нуу... это несеръёзно брадт...

Уж коли пилишь гранты - то пили хорошо.
6 авг 19, 18:23    [21943197]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
А чё в вашем ПИНГВИНЕ нулевое тестовое покрытие? Нуу... это несеръёзно брадт...

Уж коли пилишь гранты - то пили хорошо.


Ну какие гранты? Это шутка была.

Там отдельный проект есть PIGEON_PLUGINS в нём Self Testы разные, включая повторную отправку, таймауты и пр.

Руки не доходят вкорячить это в билд.
6 авг 19, 18:26    [21943198]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras
Lelouch
dakeiras,

1) Зачем каждый раз пересоздавать SslContext?
2) Зачем использовать глобальные настройки SslSocketFactory? (Любой другой код, соседствующий с этой библиотекой и использующий HttpsUrlConnection может вести себя неожидано)
3) Зачем каждый раз пересоздавать обертку для отправки запросов?


По вопросу №1 - SSLContext.getInstance("TLS") - это разве не Singletone?
Без шуток, если честно особо не глядел.

Если нет, поправлю. Не надо так делать.

По вопросу №2 - это standalone приложение, оно не подразумевает размещение на общем сервере приложений с другими.
Именно по причине глобалього defaultSSLSocketFactory.

Какие есть альтернативы setDefaultSSLSocketFactory?

По вопросу №3 - это отлично подмеченно. Поправлю.

1) В java 8 и 11 нет.
2) У вас каждый outputQueue имеет собственную настройку senderClassName. Использование SenderDefaultHttps и SenderDefaultHttpsUnsecure для разных очередей приведет к гонке на defaultSSLSocketFactory. Можно использовать HttpsUrlConnection#setSocketFactory
6 авг 19, 18:35    [21943204]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
А чего форков нету? Никому не нужен видать пингвин.
6 авг 19, 18:36    [21943205]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
А чего форков нету? Никому не нужен видать пингвин.


Ну Голубь (Pigeon, почтовый голубь) ещё не в релизе - и объективно маловероятно что кто-то в банках будет ставить нераспространённый опен сорс.
Я поговорю со своими знакомыми, может кто-то захочит поменять самописные скрипты для рассылок на это приложение.

А вот то что нет скачиваний Bobbin - вот это неожиданно... Видно настолько людям приелись существующие логгеры, что они уже не воспринимают их критично и ленятся что-то новое пробовать...
6 авг 19, 18:48    [21943212]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
HttpsUrlConnection#setSocketFactory


Спасибо, отличный совет. Так и сделаю, скоро поменяю.
6 авг 19, 18:49    [21943216]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
я вижу тут оживлённое обсуждение и других проектов пошло.

Тогда сделаю анонс: скоро будет выпущен новый проект - portable аналог Spring Security для микросервисов + авторизационный сервер к нему.

Portable значит что может использоваться с любыми платформами для микросервисов, не ограничиваясь Spring или Java вообще.
Например можно его подключить к Python.

Это будет одно из очень немногих end-to-end бесплатных решений для безопасности микросервисов - начиная от Authorization Granting и заканчивая Authorization Validation.
6 авг 19, 18:53    [21943221]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras
А вот то что нет скачиваний Bobbin - вот это неожиданно...


ну я бы тоже не стал его использовать.
Как минимум:
1) заявление о производительности, но 0 бенчмарков
2) только синхронные аппендеры
3) отсутсвие возможности перенастроить уровень логирования в runtime.
4) Необходимость тащить за логгером 5мб зависимости в виде groovy (logback например - 2 зависимости суммарно 800кб)
5) Малое количество доступных аппендеров
6) меня терзают смутные сомнения о FileDestination - КМК каждый поток может создать свой FileWriter для каждого файла и попробовать что-то туда записать. Что при этом будет с содержимым файла?
6 авг 19, 18:57    [21943227]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
7) любой exception в Destination#store просто свалит поток, вызвавший логирование...
6 авг 19, 19:00    [21943231]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
А вот то что нет скачиваний Bobbin - вот это неожиданно... Видно настолько людям приелись существующие логгеры, что они уже не воспринимают их критично и ленятся что-то новое пробовать...

Да чет не хоца. Тут прям на глазах пофиксили джуниорский баг.
Вобщем-та есть некое.... ощущение что проект - школьный.

Не обижайся уж.

Мы не злые. Просто трезвый расчет...
6 авг 19, 19:02    [21943232]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton,

автор
только синхронные аппендеры

Почему синхронные? Как раз таки полностью асинхронные. В этом выигрышь и достигается.
6 авг 19, 19:14    [21943240]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras,

что в них, простите, асинхронного? store явно вызывает FileWriter#write
6 авг 19, 19:15    [21943241]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
Тут прям на глазах пофиксили джуниорский баг.

Баг практически ни на что не влиял.
6 авг 19, 19:18    [21943243]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch,

но на каждый поток - отдельный файл :)
6 авг 19, 19:18    [21943244]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
dakeiras,

что в них, простите, асинхронного? store явно вызывает FileWriter#write


на каждый поток отдельный файл и отдельный FileWriter - полностью асинхронная запись, без потерь на synchronized.
6 авг 19, 19:19    [21943245]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras,

Это асинхронным его не делает. Кроме этого ОЧЕНЬ усложняет анализ логов.
+ Не могли бы вы показать, где к имени файла примешивается идентификатор потока?
6 авг 19, 19:20    [21943248]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras,

вот только поток каждый раз ждет, пока файл будет записан. Асинхронные аппендеры это про другое - возможность накапливать много событий в очередь и выводить их в файл 1 куском.
6 авг 19, 19:22    [21943250]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras,

Если я правильно понял, то на уровне конфигурации:
"fileName": "\"./LOGS/${threadName}/${level}/${threadName}_${level}_${date}.log\"",

при этом если пользователь НЕ укажет threadName при настроке навзания или пути файла - то видимо он ССЗБ :) прэлэстно
6 авг 19, 19:27    [21943254]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
vas0
Member

Откуда: Таможенный союз (Россия, Казахстан)
Сообщений: 1210
dakeiras
Lelouch
dakeiras,

что в них, простите, асинхронного? store явно вызывает FileWriter#write


на каждый поток отдельный файл и отдельный FileWriter - полностью асинхронная запись, без потерь на synchronized.
Код не смотрел, поэтому мой вопрос может показаться ламерский. Потери на synchronized это же не просто потери, synchronized дает гарантию visibility. Что корректное значение записаное в одним потоке, будет прочитано в другом. Как это достигается здесь, через использование immutable+final объектов или как?
6 авг 19, 19:32    [21943256]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
vas0,

ThreadLocal
6 авг 19, 19:33    [21943258]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
dakeiras,

вот только поток каждый раз ждет, пока файл будет записан. Асинхронные аппендеры это про другое - возможность накапливать много событий в очередь и выводить их в файл 1 куском.


Я понимаю про Буферизующие\асинхронные аппендеры (с отдельным тредом). Всё это было и было выпилено за вредностью\ненадобностью.

Но я не понимаю почему Вы говорите что в Бобине потоки будут ждать, пока будет записан другой файл.
Методы Бобины (store, etc) НЕ синхронные, соотвественно копируются на вызов из каждого потока АСИНХРОННО.

автор
вот только поток каждый раз ждет, пока файл будет записан.



автор
Это асинхронным его не делает. Кроме этого ОЧЕНЬ усложняет анализ логов.

Наоборот, упрощает, потоки надо группировать (threadGroupName) и логи раскидывать по папкам красиво.
У меня 200 логов я кайфую как всё под контролем.

автор
Не могли бы вы показать, где к имени файла примешивается идентификатор потока?

Это хороший вопрос.
Вот тут:
https://github.com/INFINITE-TECHNOLOGY/BOBBIN/blob/master/src/main/groovy/io/infinite/bobbin/BobbinScriptEngine.groovy

    String getThreadName() {
        return Thread.currentThread().getName()
    }

    String getThreadGroupName() {
        return Thread.currentThread().getThreadGroup().getName()
    }


Это даёт использовать неявные field reference (добавленные Groovy при компиляции на основании getter'ов выше) в имени файла:

"fileName": "\"./LOGS/THREADS/${threadGroupName}/${threadName}/${level}/${threadName}_${level}_${date}.log\""
6 авг 19, 19:34    [21943260]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
dakeiras,

Если я правильно понял, то на уровне конфигурации:
"fileName": "\"./LOGS/${threadName}/${level}/${threadName}_${level}_${date}.log\"",

при этом если пользователь НЕ укажет threadName при настроке навзания или пути файла - то видимо он ССЗБ :) прэлэстно


Да, возникнет обычный io congestion, как в других логгерах.
6 авг 19, 19:37    [21943261]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
vas0
dakeiras
пропущено...


на каждый поток отдельный файл и отдельный FileWriter - полностью асинхронная запись, без потерь на synchronized.
Код не смотрел, поэтому мой вопрос может показаться ламерский. Потери на synchronized это же не просто потери, synchronized дает гарантию visibility. Что корректное значение записаное в одним потоке, будет прочитано в другом. Как это достигается здесь, через использование immutable+final объектов или как?


Тут потоки никак не взаимодействуют.
6 авг 19, 19:38    [21943263]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Хочу ещё раз подчеркнуть - в Бобине НЕТ io waits/congestion (если отдельные файлы на каждый поток настроены).

Там нет ни одного синхронного метода, за исключением нативных методов ОС при записи по конкретному дескриптору.
6 авг 19, 19:40    [21943264]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras,
dakeiras
потоки будут ждать, пока будет записан другой файл.

Потоки будут ждать, пока будет записан ИХ файл. И да, это долго в ряде случаев.

dakeiras
Наоборот, упрощает, потоки надо группировать (threadGroupName) и логи раскидывать по папкам красиво.
У меня 200 логов я кайфую как всё под контролем.


А теперь представим что одно событие обрабатывается в нескольких потоках:
1) контроллер добавляет сообщение в очередь
2) Поток слушающий очередь, достает его, нарезает на независимые операции и запускает через Executor#invokeAll. После этого отправляет сообщение через условную atmosphere.
3) atmosphere через свой пул рассылает web socket клиентам.
Как в ваших "удобных" логах собрать весь путь сообщения? видимо только через что-то внешнее
6 авг 19, 19:41    [21943267]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
Потоки будут ждать, пока будет записан ИХ файл. И да, это долго в ряде случаев.

Идею понял.

Это тестировалось, асинхронные аппендеры - менее эффективны.
6 авг 19, 19:44    [21943271]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
vas0
Member

Откуда: Таможенный союз (Россия, Казахстан)
Сообщений: 1210
Ну если данные генерируются в каких то потоках, а в каких то других потоках идет запись в файлы. Чем тут поможет ThreadLocal?
Только если работа уже идет на уровне immutable string объектах, для объектов другого типа без синхронизации можешь получить некорректные значение.
6 авг 19, 19:44    [21943272]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras,

dakeiras
Да, возникнет обычный io congestion, как в других логгерах.

См logstash > fileAppender > prudent.
И да, в других логгерах это возникнет, если пользователь явно настроит 2 разных аппендера на 1 файл. В вашем - если не укажет настроку, которая ни разу не обязательна с его точки зрения.

dakeiras
нет io waits

С чего это вдруг их нет?
6 авг 19, 19:45    [21943273]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
А теперь представим что одно событие обрабатывается в нескольких потоках:
1) контроллер добавляет сообщение в очередь
2) Поток слушающий очередь, достает его, нарезает на независимые операции и запускает через Executor#invokeAll. После этого отправляет сообщение через условную atmosphere.
3) atmosphere через свой пул рассылает web socket клиентам.
Как в ваших "удобных" логах собрать весь путь сообщения? видимо только через что-то внешнее


Через MDC. Имя файла поддерживает MDC, будет кросс-поточный лог файл для конкретного id.
6 авг 19, 19:45    [21943274]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Точно также это делается для "username", request id, и прочего.
6 авг 19, 19:46    [21943276]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
vas0
Ну если данные генерируются в каких то потоках, а в каких то других потоках идет запись в файлы. Чем тут поможет ThreadLocal?
Только если работа уже идет на уровне immutable string объектах, для объектов другого типа без синхронизации можешь получить некорректные значение.


Данные генерируются и записываются в рамках 1 потока.
6 авг 19, 19:47    [21943277]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras,


dakeiras
Это тестировалось, асинхронные аппендеры - менее эффективны.


Они более эффективны даже с точки зрения скорости записи этого самого файла, потому что могут писать его 1 куском. Посмотрите хотя тесты последовательного чтения/записи (например по 1мб) и рандомного (по 4к во всяких crystal disk)
6 авг 19, 19:47    [21943278]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras
Через MDC. Имя файла поддерживает MDC, будет кросс-поточный лог файл для конкретного id.


То есть чтобы не страдать от вашего логгера, пользователь обязан использовать MDC?
6 авг 19, 19:48    [21943279]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Кстати Бобина даёт невиданный функционал по кросс-поточному и кросс-классовому отслеживанию действий юзера - очень легко настроить чтобы на каждого юзера (или отдельного юзера) были свои лог файлы, через MDC.

Теперь видите какой это царский функционал?
6 авг 19, 19:49    [21943280]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
dakeiras
Через MDC. Имя файла поддерживает MDC, будет кросс-поточный лог файл для конкретного id.


То есть чтобы не страдать от вашего логгера, пользователь обязан использовать MDC?


В других логгерах это без MDC не сделать. Только там будет общий файл-каша.
А тут отдельные файлы.

Единственная альтернатива - переименовывать потоки, что не рекомендуется.
6 авг 19, 19:51    [21943281]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
См logstash > fileAppender > prudent.
И да, в других логгерах это возникнет, если пользователь явно настроит 2 разных аппендера на 1 файл. В вашем - если не укажет настроку, которая ни разу не обязательна с его точки зрения.


Посмотрю, спасибо.

автор
Они более эффективны даже с точки зрения скорости записи этого самого файла, потому что могут писать его 1 куском. Посмотрите хотя тесты последовательного чтения/записи (например по 1мб) и рандомного (по 4к во всяких crystal disk)


Это тоже посмотрю. Благодарю.
6 авг 19, 19:53    [21943282]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras
Кстати Бобина даёт невиданный функционал по кросс-поточному и кросс-классовому отслеживанию действий юзера - очень легко настроить чтобы на каждого юзера (или отдельного юзера) были свои лог файлы, через MDC.

Теперь видите какой это царский функционал?


Нет не вижу.
Что по остальным пунктам? Например IOException при ошибке записи файла.
6 авг 19, 19:54    [21943283]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
vas0
Member

Откуда: Таможенный союз (Россия, Казахстан)
Сообщений: 1210
dakeiras
vas0
Ну если данные генерируются в каких то потоках, а в каких то других потоках идет запись в файлы. Чем тут поможет ThreadLocal?
Только если работа уже идет на уровне immutable string объектах, для объектов другого типа без синхронизации можешь получить некорректные значение.


Данные генерируются и записываются в рамках 1 потока.
А как же асинхронные апендеры?
6 авг 19, 19:57    [21943285]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
vas0
dakeiras
пропущено...


Данные генерируются и записываются в рамках 1 потока.
А как же асинхронные апендеры?

Их нет. Тут ничего нет кроме консоли и файла. Кстати, dakeiras, вы в курсе, что System.out.println синхронный?
6 авг 19, 19:59    [21943286]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
Lelouch
vas0
пропущено...
А как же асинхронные апендеры?

Их нет. Тут ничего нет кроме консоли и файла. Кстати, dakeiras, вы в курсе, что System.out.println синхронный?


Даже уточню - выполняет синхронизацию на this.
6 авг 19, 20:01    [21943288]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
[quot dakeiras]В других логгерах это без MDC не сделать. Только там будет общий файл-каша.
Решается условным graylog. И это удобнее чем "куча файлов"
6 авг 19, 20:02    [21943289]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras,

ну и на последок хочу заметить, что ваш логгер в том числе не защищен от случая, когда 2 потока имеют одинаковое название.
https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setName(java.lang.String)
Every thread has a name for identification purposes. More than one thread may have the same name. If a name is not specified when a thread is created, a new name is generated for it.


Нигде в документации не заостряется, что имя файла явно должно содержать threadName в настройках шаблона имени файла и не указано требование уникальности имени потока (или уникальности пары threadGroupName и threadName).

В том числе, если какая-либо сторонняя библиотека по ошибке, или специально, создает потоки с одинаковыми названиями - это делает стабильную работу вашего логгера не возможной.

Как когда-то выразился мой преподавать на 1 курсе:
Ваша программа представляет из себя хрупкую игрушку, работающую только в руках создателя.
6 авг 19, 20:29    [21943299]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
Кстати Бобина даёт невиданный функционал по кросс-поточному и кросс-классовому отслеживанию действий юзера - очень легко настроить чтобы на каждого юзера (или отдельного юзера) были свои лог файлы, через MDC.

Теперь видите какой это царский функционал?

Обычно (в 99%) случаев настройкой системы логгирования заняты дев-опсы. И они себе ставят
вполне себе конкретные задачи. Как-то
- безопасность и аудит
- перформанс
- анализ ошибок

Для всех этих задач этот царский функционал не нужен. Ну или я не знаю такого юзкейса.
Логгировать отдельно поток нет никакого смысла. Поток - это ресурс который берут из "обоймы"
доступных ресурсов и роль потока в крупном приложении может серъезно менятся в считанные
секунды.

Вести одновременно 200 логов с точки зрения файловой системы накладно т.к. нужно иметь
200 файловых дескрипторов и соотв 200 объектов представляющих файл (буферов). Накладные
расходы можно считать а можно и нет. Но поинт опять-же в том что это может быть накладно
(так-же как и держать 65000 открытых сокетов на веб-сервере) и иногда количество переходит
в качество. Для старых магнитных накопителей время seektime безсмысленно тратится
на беготню по поверхности диска и вы получаете жалкие 25 мегабайт в секунду потому-что
вместо throughput получили IOPS, и чтобы получить паспортные пропускные способности
диска - вам лучше вернуться к классической схеме где есть 1 или 2 лога на всё приложение.

Если-же вы слишком долго буферизируете лог без флаша то рискуете получить недописанные
хвостики логов в случае краша приложения.

Зачем нужны логи без хвостиков - я не знаю. Это epic fail и такие логи не будут отражать
важные действия которые возможно повлекли за собой падение.

Провертье мою гипотезу. Нажмите reset под нагрузкой и проследите что самые последние
бизнес аудиты были сохранены.
6 авг 19, 22:21    [21943343]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
Обычно (в 99%) случаев настройкой системы логгирования заняты дев-опсы. И они себе ставят
вполне себе конкретные задачи. Как-то
- безопасность и аудит
- перформанс
- анализ ошибок

Для всех этих задач этот царский функционал не нужен. Ну или я не знаю такого юзкейса.
Логгировать отдельно поток нет никакого смысла. Поток - это ресурс который берут из "обоймы"
доступных ресурсов и роль потока в крупном приложении может серъезно менятся в считанные
секунды.

Я завтра с работы подробно отвечу на комментарии.

Касательно ELK - там невозможно вручную логи смотреть, поэтому отдельные файлы на каждый лог - дают выигрыш в производительности - за счёт отсутствия io congestion.

Если нет ELK, в случаях с пакетными приложениями, ETL, индустриальными приложениями с фиксированными потоками - там возможность отдельных лог файлов это супер фича.
Когда требуется вручную разбирать лог файлы. И в процессе отладки приложения.
6 авг 19, 22:44    [21943350]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
dakeiras,

ну и на последок хочу заметить, что ваш логгер в том числе не защищен от случая, когда 2 потока имеют одинаковое название.
https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setName(java.lang.String)
Every thread has a name for identification purposes. More than one thread may have the same name. If a name is not specified when a thread is created, a new name is generated for it.


Нигде в документации не заостряется, что имя файла явно должно содержать threadName в настройках шаблона имени файла и не указано требование уникальности имени потока (или уникальности пары threadGroupName и threadName).

В том числе, если какая-либо сторонняя библиотека по ошибке, или специально, создает потоки с одинаковыми названиями - это делает стабильную работу вашего логгера не возможной.

Как когда-то выразился мой преподавать на 1 курсе:
Ваша программа представляет из себя хрупкую игрушку, работающую только в руках создателя.


Никто не говорит, что обязательно разделять.

Просто с точки зрения здравого смысла, если у вас есть 500 потоков - писать лог в единый файл - это бред, наркомания укоренившаяся с годами.
Т.к. очевидно что это вызывает очередь на запись в этот файл.

Хрупкая или нет - есть артифакты публично доступные через Magen/Gradle.

Качаем, ломаем - я плачу бабло.
У меня принцип - ОТВЕЧАТЬ за свой опен сорс софт.

PS: если не нравится threadName, ну напишите threadName+Thread.currentThread().getId()
6 авг 19, 22:59    [21943363]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Т.е. хотите - делайте 1 файл на поток, хотите отдельные файлы по уровням, Бобина всё это отлично поддерживает.

Никаких умозрительных ограничений и незадокументированных архитектурных проблем нет.
6 авг 19, 23:04    [21943366]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Пока я отвечу более детально, прошу всех скачать Бобину (через Maven, Gradle, jar - как удобно) и просто начать ей пользоваться.

Настроить по своим предпочтениям. И наслаждаться свободой от ига logback и прочих log4j.
6 авг 19, 23:06    [21943367]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Релиз 2.0.5 - он с учётом фидбека из этой темы.
6 авг 19, 23:10    [21943369]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
Я завтра с работы подробно отвечу на комментарии.

Касательно ELK - там невозможно вручную логи смотреть, поэтому отдельные файлы на каждый лог - дают выигрыш в производительности - за счёт отсутствия io congestion.

Если нет ELK, в случаях с пакетными приложениями, ETL, индустриальными приложениями с фиксированными потоками - там возможность отдельных лог файлов это супер фича.
Когда требуется вручную разбирать лог файлы. И в процессе отладки приложения.

А что касательно Elastic-Kibana? Речь вообще про него не идёт.
Или вы делаете узкоспециализированное решение?
6 авг 19, 23:29    [21943375]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
Пока я отвечу более детально, прошу всех скачать Бобину (через Maven, Gradle, jar - как удобно) и просто начать ей пользоваться.

Настроить по своим предпочтениям. И наслаждаться свободой от ига logback и прочих log4j.

А ты хитрец. Хочешь бесплатную бригаду тестировщиков?

Ты с Панфиловым расчитался?
6 авг 19, 23:34    [21943376]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
Пока я отвечу более детально, прошу всех скачать Бобину (через Maven, Gradle, jar - как удобно) и просто начать ей пользоваться.

Настроить по своим предпочтениям. И наслаждаться свободой от ига logback и прочих log4j.

А ты хитрец. Хочешь бесплатную бригаду тестировщиков?

Ты с Панфиловым расчитался?

конечно! Ща как затестирую за ваш счет да как раскручусь, донат польётся рекой.

Кстати, правительсто оплачивает мне 10 опер сорс проектов, но я выкладываю только 5, остальные сам использую.

Как с тем армянином (который к сожалению умер) и бесплатным хлебом.
6 авг 19, 23:40    [21943377]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 9224
dakeiras
Можно пример как это настраивается в Log4j без изменения пользовательского кода?
Сейчас уже сложно найти ссылку на общедоступное руководство по log4j 1.2, поэтому я дал ссылку на документацию, где есть говорящее "andWatch". XML-конфигурация регулярно проверяется на обновление (мониторится дата-время xml-файла и, возможно, его размер). Если изменение обнаружено - запускается процесс переконфигурации.

Практически, когда мне потребовалось написать XML-конфигурацию log4j, то, лично я, сделать этого не смог - не разобрался с DTD. Зато, после недолгих поисков, нашёл онлайновый конвертор, скормил ему простую конфигурацию из файла свойств и получил шаблон, который потом менял под собственные нужды. Всё это проделывалось лет шесть назад и прекрасно работало.
7 авг 19, 06:36    [21943398]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 9224
dakeiras
Просто с точки зрения здравого смысла, если у вас есть 500 потоков - писать лог в единый файл - это бред, наркомания укоренившаяся с годами.
Нет задачи "писать лог в единый файл" и наркомания тут совершенно не в тему.
Если анализ проблемы требует анализ данных от пятисот потоков - так тому и быть.
И вот в этом случае собирать и синхронизировать данные из пятисот логов - проще сразу убиться, предварительно застрелив автора этой гениальной задумки.
7 авг 19, 06:47    [21943401]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3258
dakeiras
Андрей нашёл 1 явный баг (minor)

У вас какое-то определение minor/major несколько странное... Вы внимательно читали выхлоп от 21941782? Там mm, dd, yyyy и пр. не полностью замещаются, а перемешиваются, т.е. на "границах" разница получается на самом деле не микросекунды, а секунды, минуты, часы, месяцы, годы - если такой лог куда-то грузить для дальнейшего анализа, то в нем сообщения будут банально теряться.

dakeiras
1 потенциальный баг с max open files exceeded
т.е. до конца раскрутить вы замечание не смогли, а вот Lelouch смог 21943227:
Lelouch
6) меня терзают смутные сомнения о FileDestination - КМК каждый поток может создать свой FileWriter для каждого файла и попробовать что-то туда записать. Что при этом будет с содержимым файла?
7 авг 19, 07:27    [21943407]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 1019
Basil A. Sidorov,
Вроде стандартная фича логеров, писать в один файл, но после времени идёт id потока.
Удобно.
7 авг 19, 08:15    [21943430]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras,

Хотели тесты - получайте

https://github.com/oleg-zinovev/bobbin-test-suite

1) TestIOExceptionOnLog - показывает, что в случае ошибки IO полезная работа (в данном случае установка флага work) не выполняется. Для демонстрации этого кейса на Windows можно указать несуществующий диск (вместо /some/missing/root/directory/on/my/mac). На *nix достаточно запустить от пользователя, который не имеет права на запись в /.

2) TestSameName - показывает ошибки при одинаковом имени файла. На Windows возможно тест завершиться с ошибкой на первых 3х ассретах. Так как *nix позволяет писать в один файл из нескольких процессов/потоков, для демонстрации проблемы пришлось сгенерировать строку лога, превышающий размеры буфера записи в FileWriter (возможно, есть меньший размер буфера, при котором начнется перемешивание, связанный с работой файловой системы, но тут я хз). При этом на *nix ошибок записи нет, но содержимое логов перемешивается. Последний assert проверяет именно это.
7 авг 19, 09:11    [21943454]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Basil A. Sidorov
dakeiras
Просто с точки зрения здравого смысла, если у вас есть 500 потоков - писать лог в единый файл - это бред, наркомания укоренившаяся с годами.
Нет задачи "писать лог в единый файл" и наркомания тут совершенно не в тему.
Если анализ проблемы требует анализ данных от пятисот потоков - так тому и быть.
И вот в этом случае собирать и синхронизировать данные из пятисот логов - проще сразу убиться, предварительно застрелив автора этой гениальной задумки.


Логгер «Бобина» позволяет удобно настраивать отображения вывода данных логирования в разных проекциях, в зависимости от необходимости:

- По потокам
- По уровню сообщения (error, debug, etc)
- По классам
- По MDC - например отслеживать работу по конкретному пользователю или по конкретному transaction id

Эти критерии можно группировать и комбинировать как угодно, например по группам потоков, пакетам классов - ограничений нет никаких.

1 сообщение может выводится во множество файлов одновременно.

Всё ещё хочется застрелить за такую идею? Плохая идея?

По остальным комментариям - отвечу с работы, заранее большое спасибо за тесты и фидбек.
7 авг 19, 12:51    [21943712]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras
Всё ещё хочется застрелить за такую идею? Плохая идея?


За идею вас тут никто не расстреливают, просто никто кроме вас не видит преимуществ в этой идеи.
А вот реализация идеи хромает.
7 авг 19, 12:57    [21943721]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
dakeiras
Всё ещё хочется застрелить за такую идею? Плохая идея?


За идею вас тут никто не расстреливают, просто никто кроме вас не видит преимуществ в этой идеи.
А вот реализация идеи хромает.


Человек выше написал:

автор
застрелив автора этой гениальной задумки


Мне лично хочется самому застрелиться от конфигов logback и log4jX.

Сейчас начну смотреть тесты и комменты.
7 авг 19, 13:55    [21943782]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch,

Огромное спасибо, что потратили время и сделали тесты.
Сейчас буду смотреть.

Респект.
7 авг 19, 13:58    [21943785]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
Lelouch
пропущено...


За идею вас тут никто не расстреливают, просто никто кроме вас не видит преимуществ в этой идеи.
А вот реализация идеи хромает.


Человек выше написал:

автор
застрелив автора этой гениальной задумки


Мне лично хочется самому застрелиться от конфигов logback и log4jX.

Сейчас начну смотреть тесты и комменты.

Ты ставишь нас в глупое положение. Ведь мы не видим те ужасные конфиги на которые
ты смотришь сейчас. Сделай милость. Приведи конфиг для одинаковой конфигурации для Робин-Катушка-Толтсяк
и Лог4Джей и Логбэк.
7 авг 19, 14:04    [21943792]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
пропущено...


Человек выше написал:

пропущено...


Мне лично хочется самому застрелиться от конфигов logback и log4jX.

Сейчас начну смотреть тесты и комменты.

Ты ставишь нас в глупое положение. Ведь мы не видим те ужасные конфиги на которые
ты смотришь сейчас. Сделай милость. Приведи конфиг для одинаковой конфигурации для Робин-Катушка-Толтсяк
и Лог4Джей и Логбэк.


Вот несколько моментов описано:
https://github.com/INFINITE-TECHNOLOGY/BOBBIN/wiki/1---Introduction#problems

Это если чуть конкретнее.

Но в общем случае конфиги Бобины просто невоспроизводимы в других логгерах из-за функциональных ограничений SiftingAppender - либо огромные по размеру (отдельные блоки НА КАЖДЫЙ КЛАСС либо на весь пакет целиком)
7 авг 19, 14:30    [21943825]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras, ты пишешь

Existing logging solutions provide only partial support for scripting in configuration.

Поясни эту фразу. Что значит scripting in configuration? Где partial? И где может быть full?
7 авг 19, 14:34    [21943831]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch,

Посмотрел 1й тест: TestIOExceptionOnLog

Сделал PR: https://github.com/oleg-zinovev/bobbin-test-suite/pull/1

Бобина есть в JCenter, не обязательно ещё её собвстенный репозиторий подключать, это описано в инструкции:
https://github.com/INFINITE-TECHNOLOGY/BOBBIN/wiki/3---Usage#add-maven-dependency

Так же тест не воспроизводился под виндой из-за UAC Virtualization. Я чуть подправил.

Теперь касательно сути самого теста: это осмысленное поведение.
Я считаю, что выполнение не должно продолжаться при отказе системы логирования.

Принцип такой: чем раньше упадёт - тем лучше. А шанс того что упадёт само приложение чуть позже, если упал логгер - есть.

Это очередная "гениальная" фича в Logback - супрессить ошибки в логгере.
7 авг 19, 14:53    [21943842]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras, ты пишешь

Existing logging solutions provide only partial support for scripting in configuration.

Поясни эту фразу. Что значит scripting in configuration? Где partial? И где может быть full?


В Бобине full support скриптинга в конфиге, все поля это скрипты:
- levels
- classes
- fileName
- format
и пр.

Partial из документации к Бобине:
Note: Logback supports Groovy Script filter - but it is applicable only on specific appender configuration, not on Logger configuration.

Т.е. только фильтр и только на уровне аппендеров...
7 авг 19, 14:55    [21943846]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch, сейчас посмотрю второй тест.
7 авг 19, 14:56    [21943847]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Mayton,

Вот ещё про Full support:

https://github.com/INFINITE-TECHNOLOGY/BOBBIN/wiki/1---Introduction#full-support-for-scripting-in-logger-run-time-configuration-files
7 авг 19, 14:58    [21943849]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton
dakeiras, ты пишешь

пропущено...

Поясни эту фразу. Что значит scripting in configuration? Где partial? И где может быть full?


В Бобине full support скриптинга в конфиге, все поля это скрипты:
- levels
- classes
- fileName
- format
и пр.

Partial из документации к Бобине:
Note: Logback supports Groovy Script filter - but it is applicable only on specific appender configuration, not on Logger configuration.

Т.е. только фильтр и только на уровне аппендеров...

Но ты понимаешь что есть семантическое различие между конфигом и кодом?

В коде находят ошибки другого рода. Код сложнее тестировать. Код вообще
в общем случае корректен недоказуемо.

Конфиг - всегда корректен если просто прошел валидацию.

Ты, беря возможности Groovy перенёс часть логики в конфиги и выставил это как преимущество.
Но на самом деле это не разу не приемущество. Это - недостаток. Это - ненадёжность системы.
7 авг 19, 15:02    [21943852]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
пропущено...


В Бобине full support скриптинга в конфиге, все поля это скрипты:
- levels
- classes
- fileName
- format
и пр.

Partial из документации к Бобине:
пропущено...

Т.е. только фильтр и только на уровне аппендеров...

Но ты понимаешь что есть семантическое различие между конфигом и кодом?

В коде находят ошибки другого рода. Код сложнее тестировать. Код вообще
в общем случае корректен недоказуемо.

Конфиг - всегда корректен если просто прошел валидацию.

Ты, беря возможности Groovy перенёс часть логики в конфиги и выставил это как преимущество.
Но на самом деле это не разу не приемущество. Это - недостаток. Это - ненадёжность системы.


Вот. Прямо в точку.

Нет разницы между конфигом и кодом.

Есть единая система - с изменениями на этапах:
1) Сборки\компиляции
2) Запуска (старта) работы\перезапуске
3) В Runtime

Всё.

То что в конфигах не должны быть скрипты - это миф, страшилка родом из 90х.
Типа тормозит, небезопасно и пр. Это всё несостоятельно, и в результате приводит к декларативному программированию в конфигах (https://github.com/INFINITE-TECHNOLOGY/BOBBIN/wiki/1---Introduction#declarative-programming-in-logger-configuration)
а также к изобретению волшебных синтаксисов.

А также типа пользователь не разберётся как настроить. Если дев опс не в состоянии осилить скрипт - он по определению не дев опс.
7 авг 19, 15:13    [21943873]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
То что в конфигах не должны быть скрипты - это миф, страшилка родом из 90х.
Типа тормозит, небезопасно и пр. Это всё несостоятельно, и в результате приводит к декларативному программированию в конфигах (https://github.com/INFINITE-TECHNOLOGY/BOBBIN/wiki/1---Introduction#declarative-programming-in-logger-configuration)
а также к изобретению волшебных синтаксисов.

А также типа пользователь не разберётся как настроить. Если дев опс не в состоянии осилить скрипт - он по определению не дев опс.

Капец какой-то. Вот ты Windows используешь. И тестишь на нем своего Толстого-Робина
(отдельный вопрос почему ибо не энтерпрайзно. но потом спрошу) но хоть раз заглядывал
в самое крупное хранилище настрек Windows. А именно в Windows-registry?
7 авг 19, 15:27    [21943884]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch,

Касательно второго теста - там ошибка не в truncation, строка содержит данные от нескольких потоков.
Т.к. 1 общий файл настроен.

Наверное всё таки придётся добавить synchronized(file) в store...

Сейчас подумаю.
7 авг 19, 15:27    [21943885]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
То что в конфигах не должны быть скрипты - это миф, страшилка родом из 90х.
Типа тормозит, небезопасно и пр. Это всё несостоятельно, и в результате приводит к декларативному программированию в конфигах (https://github.com/INFINITE-TECHNOLOGY/BOBBIN/wiki/1---Introduction#declarative-programming-in-logger-configuration)
а также к изобретению волшебных синтаксисов.

А также типа пользователь не разберётся как настроить. Если дев опс не в состоянии осилить скрипт - он по определению не дев опс.

Капец какой-то. Вот ты Windows используешь. И тестишь на нем своего Толстого-Робина
(отдельный вопрос почему ибо не энтерпрайзно. но потом спрошу) но хоть раз заглядывал
в самое крупное хранилище настрек Windows. А именно в Windows-registry?


Что значит не ентерпрайзно? Зачем какие-то предосуждения?
Всё в CI, Travis CI, автоматизированные билды, snapshots.

https://travis-ci.com/INFINITE-TECHNOLOGY/BOBBIN

Не разобрались и уже негативные предрассудки.

Насчёт Windows registry - стараюсь туда не заглядывать, в эту помойку.
7 авг 19, 15:30    [21943891]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton
пропущено...

Капец какой-то. Вот ты Windows используешь. И тестишь на нем своего Толстого-Робина
(отдельный вопрос почему ибо не энтерпрайзно. но потом спрошу) но хоть раз заглядывал
в самое крупное хранилище настрек Windows. А именно в Windows-registry?


Что значит не ентерпрайзно? Зачем какие-то предосуждения?
Всё в CI, Travis CI, автоматизированные билды, snapshots.

https://travis-ci.com/INFINITE-TECHNOLOGY/BOBBIN

Не разобрались и уже негативные предрассудки.

Насчёт Windows registry - стараюсь туда не заглядывать, в эту помойку.

Ну вот загляни. Там - нет кода. Ну 99.99% нет.
Просто концепция такая. И слава богу что нет.
Когда появится код - сопровождать систему станет на порядки сложно.
Потому что покорректировать параметр с 5 на 10 стоит одних человеческих усилий.
А просмотреть SPEL/MVEL или любой другой сниппет - уже можешь подряжать
в работу разаработчика.

А доказательтво правоты кода - вообще отдельная история. Об этом еще Гильберт
писал. О полноте...
7 авг 19, 15:33    [21943899]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 1019
dakeiras
Нет разницы между конфигом и кодом.
прикольно).
Вот оно - ФП.
7 авг 19, 15:34    [21943900]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras,

Посмотрев ваш PR, хотелось бы уточнить - как вы поняли проблему теста TestIOExceptionOnLog?
7 авг 19, 15:35    [21943903]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras
Lelouch,

Касательно второго теста - там ошибка не в truncation, строка содержит данные от нескольких потоков.
Т.к. 1 общий файл настроен.

Наверное всё таки придётся добавить synchronized(file) в store...

Сейчас подумаю.

А где я написал что ошибка в truncation ??? Цитату пожалуйста. Ошибка в смешивании содержимого
7 авг 19, 15:36    [21943905]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
PetroNotC Sharp
dakeiras
Нет разницы между конфигом и кодом.
прикольно).
Вот оно - ФП.

(морщится)

Нет. Это не ФП. Это просто перенос complexity с одной части кода в другую.

У ФП есть конкретный перечень признаков. Кажется профессор Душкин
писал в своей книге задачи и проблемы которые конкретно решает ФП.

То что делает автор к ФП не отностится.
7 авг 19, 15:39    [21943910]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
dakeiras
Lelouch,

Касательно второго теста - там ошибка не в truncation, строка содержит данные от нескольких потоков.
Т.к. 1 общий файл настроен.

Наверное всё таки придётся добавить synchronized(file) в store...

Сейчас подумаю.

А где я написал что ошибка в truncation ??? Цитату пожалуйста. Ошибка в смешивании содержимого


Сорян, не так понял.

Это очень крутой баг Вы нашли.

Большое спасибо.

Сейчас исправлю.

Думаю сделать синхронизацию по canonicalName файла (строке).
7 авг 19, 15:47    [21943917]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
dakeiras,

Посмотрев ваш PR, хотелось бы уточнить - как вы поняли проблему теста TestIOExceptionOnLog?


Если диск переполняется или неправильные настройки Бобины (она не инициализируется), Вы бы хотели чтобы всё работало дальше - если Логгер не пашет.

Правильно понял Вас?
7 авг 19, 15:49    [21943918]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 1019
mayton,

Ок. Раз названия нету, назовем это конфигуразмом. Когда вместо программирования выносим в конфиг.
7 авг 19, 15:51    [21943920]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
пропущено...


Что значит не ентерпрайзно? Зачем какие-то предосуждения?
Всё в CI, Travis CI, автоматизированные билды, snapshots.

https://travis-ci.com/INFINITE-TECHNOLOGY/BOBBIN

Не разобрались и уже негативные предрассудки.

Насчёт Windows registry - стараюсь туда не заглядывать, в эту помойку.

Ну вот загляни. Там - нет кода. Ну 99.99% нет.
Просто концепция такая. И слава богу что нет.
Когда появится код - сопровождать систему станет на порядки сложно.
Потому что покорректировать параметр с 5 на 10 стоит одних человеческих усилий.
А просмотреть SPEL/MVEL или любой другой сниппет - уже можешь подряжать
в работу разаработчика.

А доказательтво правоты кода - вообще отдельная история. Об этом еще Гильберт
писал. О полноте...


Сорри, но это бесполезно. Спорить с людьми которые уверены что "конфиги не должны содержать динамически интерпретируемые скрипты". Это банальные предрассудки.
7 авг 19, 15:55    [21943923]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
PetroNotC Sharp
mayton,

Ок. Раз названия нету, назовем это конфигуразмом. Когда вместо программирования выносим в конфиг.


Нет. Декларативное XML программирование (logback.xml) переносится в императивное программирование Groovy (Bobbin.json).

Пример:
автор
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>


Вы считаете что это удобно?
7 авг 19, 15:58    [21943926]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
PetroNotC Sharp
mayton,

Ок. Раз названия нету, назовем это конфигуразмом. Когда вместо программирования выносим в конфиг.

Я помню что ребят из поддержки 1С часто назыли "конфигурастами".

Им обидно наверное было...
7 авг 19, 16:00    [21943927]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 9224
dakeiras
Принцип такой: чем раньше упадёт - тем лучше. А шанс того что упадёт само приложение чуть позже, если упал логгер - есть.

Это очередная "гениальная" фича в Logback - супрессить ошибки в логгере.
Как человек, который более шести лет отработал в техподдержке региональной информационной системы, могу ответственно заявить, что с таким подходом вас примут только такие маргиналы, как и вы сами.
Задача любой системы - обслуживать пользователей. Протоколирование ошибок - всего лишь приятный бонус для разработчика. Но, тем, кто эксплуатирует систему, в достаточной степени наплевать на ваше (разработчика) удобство.
7 авг 19, 16:00    [21943928]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Log4j2 (текущих версий) конфигурится "ямлом".

https://logging.apache.org/log4j/2.x/manual/configuration.html

Достаточно лаконично. Тоесть лаконично настолько чтобы вообще не думать даже о какой-либо минимизации конфигов.
7 авг 19, 16:02    [21943929]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 9224
mayton
dakeiras
Насчёт Windows registry - стараюсь туда не заглядывать, в эту помойку.
Ну вот загляни. Там - нет кода. Ну 99.99% нет.
Вот-вот
Один вариантов сохранения "бестелесых" вирусов - хранение кода в реестре.
7 авг 19, 16:03    [21943931]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Basil A. Sidorov
mayton
пропущено...
Ну вот загляни. Там - нет кода. Ну 99.99% нет.
Вот-вот
Один вариантов сохранения "бестелесых" вирусов - хранение кода в реестре.

Ну эт. в тему стеганографии. Насколько я помню в таких случаях тело вируса безвредно.
И может годами лежать у вас локально и не тревожить.

А антивирус ищет даже не это тело а сам бут-страппер который должен это тело найти
и раскрутить дальше.

Помните RARJpeg и картинки с котиками где страшным водяным знаком прошито туловище
какого-нить wanna-cry или васи-вымогателя.
7 авг 19, 16:07    [21943937]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
[quot Basil A. Sidorov]
dakeiras
Протоколирование ошибок - всего лишь приятный бонус для разработчика.


К сообщению приложен файл. Размер - 4Kb
7 авг 19, 16:10    [21943944]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
Log4j2 (текущих версий) конфигурится "ямлом".

https://logging.apache.org/log4j/2.x/manual/configuration.html

Достаточно лаконично. Тоесть лаконично настолько чтобы вообще не думать даже о какой-либо минимизации конфигов.


А ну раз ямлом - то заебись! Пойду напишу вручную ямл на пару страниц.
И потом умру тихо.
7 авг 19, 16:11    [21943947]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 1019
mayton
PetroNotC Sharp
mayton,

Ок. Раз названия нету, назовем это конфигуразмом. Когда вместо программирования выносим в конфиг.

Я помню что ребят из поддержки 1С часто назыли "конфигурастами".

Им обидно наверное было...
да, называли)). Пусть относятся к этому с юмором.
У нас тоже, декларативное программирование это конфигуразм.
))
7 авг 19, 16:13    [21943949]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch,

Пофиксил перемешивание данных.

Сейчас выложу версию.
7 авг 19, 16:20    [21943956]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton
Log4j2 (текущих версий) конфигурится "ямлом".

https://logging.apache.org/log4j/2.x/manual/configuration.html

Достаточно лаконично. Тоесть лаконично настолько чтобы вообще не думать даже о какой-либо минимизации конфигов.


А ну раз ямлом - то заебись! Пойду напишу вручную ямл на пару страниц.
И потом умру тихо.

Я так и не дождался образца твоего конфига.
7 авг 19, 16:25    [21943961]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
PetroNotC Sharp
mayton
пропущено...

Я помню что ребят из поддержки 1С часто назыли "конфигурастами".

Им обидно наверное было...
да, называли)). Пусть относятся к этому с юмором.
У нас тоже, декларативное программирование это конфигуразм.
))

Язык Пролог - декларативен почти совсем. И ничо. Работает в своем сегменте.
7 авг 19, 16:27    [21943965]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
пропущено...


А ну раз ямлом - то заебись! Пойду напишу вручную ямл на пару страниц.
И потом умру тихо.

Я так и не дождался образца твоего конфига.


<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="InfiniteDebug" class="ch.qos.logback.classic.sift.SiftingAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <discriminator>
            <key>automaticThreadName</key>
            <defaultValue>Unnamed Thread</defaultValue>
        </discriminator>
        <sift>
            <appender name="${automaticThreadName}" class="ch.qos.logback.core.rolling.RollingFileAppender">
                <file>./LOGS/${automaticThreadName}/DEBUG/${automaticThreadName}_DEBUG_TODAY.log</file>
                <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                    <Pattern>%d{yyyy-MM-dd HH:mm:ss}:%level:%thread:%logger:%msg%n</Pattern>
                </encoder>
                <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                    <FileNamePattern>./LOGS/${automaticThreadName}/DEBUG/ARCHIVE/%d{yyyyMMdd, aux}/${automaticThreadName}_%d{yyyyMMdd}_DEBUG.zip</FileNamePattern>
                </rollingPolicy>
            </appender>
        </sift>
    </appender>
    <appender name="InfiniteInfo" class="ch.qos.logback.classic.sift.SiftingAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <discriminator>
            <key>automaticThreadName</key>
            <defaultValue>Unnamed Thread</defaultValue>
        </discriminator>
        <sift>
            <appender name="${automaticThreadName}" class="ch.qos.logback.core.rolling.RollingFileAppender">
                <file>./LOGS/${automaticThreadName}/INFO/${automaticThreadName}_INFO_TODAY.log</file>
                <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                    <Pattern>%d{yyyy-MM-dd HH:mm:ss}:%level:%thread:%logger:%msg%n</Pattern>
                </encoder>
                <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                    <FileNamePattern>./LOGS/${automaticThreadName}/INFO/ARCHIVE/%d{yyyyMMdd, aux}/${automaticThreadName}_%d{yyyyMMdd}_INFO.zip</FileNamePattern>
                </rollingPolicy>
            </appender>
        </sift>
    </appender>
    <appender name="InfiniteWarn" class="ch.qos.logback.classic.sift.SiftingAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <discriminator>
            <key>automaticThreadName</key>
            <defaultValue>Unnamed Thread</defaultValue>
        </discriminator>
        <sift>
            <appender name="${automaticThreadName}" class="ch.qos.logback.core.rolling.RollingFileAppender">
                <file>./LOGS/${automaticThreadName}/WARN/${automaticThreadName}_WARN_TODAY.log</file>
                <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                    <Pattern>%d{yyyy-MM-dd HH:mm:ss}:%level:%thread:%logger:%msg%n</Pattern>
                </encoder>
                <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                    <FileNamePattern>./LOGS/${automaticThreadName}/WARN/ARCHIVE/%d{yyyyMMdd, aux}/${automaticThreadName}_%d{yyyyMMdd}_WARN.zip</FileNamePattern>
                </rollingPolicy>
            </appender>
        </sift>
    </appender>
    <appender name="InfiniteError" class="ch.qos.logback.classic.sift.SiftingAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <discriminator>
            <key>automaticThreadName</key>
            <defaultValue>Unnamed Thread</defaultValue>
        </discriminator>
        <sift>
            <appender name="DEBUG_${automaticThreadName}" class="ch.qos.logback.core.rolling.RollingFileAppender">
                <file>./LOGS/${automaticThreadName}/ERROR/${automaticThreadName}_ERROR_TODAY.log</file>
                <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                    <Pattern>%d{yyyy-MM-dd HH:mm:ss}:%level:%thread:%logger:%msg%n</Pattern>
                </encoder>
                <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                    <FileNamePattern>./LOGS/${automaticThreadName}/ERROR/ARCHIVE/%d{yyyyMMdd, aux}/${automaticThreadName}_%d{yyyyMMdd}_ERROR.zip</FileNamePattern>
                </rollingPolicy>
            </appender>
        </sift>
    </appender>
    <appender name="System.out" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{yyyy-MM-dd HH:mm:ss}:%level:%thread:%logger:%msg%n</Pattern>
        </encoder>
    </appender>
    <logger name="io.infinite" level="debug" additivity="false">
        <appender-ref ref="InfiniteDebug"/>
        <appender-ref ref="InfiniteInfo"/>
        <appender-ref ref="InfiniteWarn"/>
        <appender-ref ref="InfiniteError"/>
    </logger>
    <root level="info">
        <appender-ref ref="System.out"/>
    </root>
</configuration>
7 авг 19, 16:35    [21943976]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 1019
dakeiras,
А теперь рядом минимальный с логами default.
7 авг 19, 16:48    [21943990]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
PetroNotC Sharp
dakeiras,
А теперь рядом минимальный с логами default.


Зачем?
7 авг 19, 16:54    [21943995]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras
Lelouch,

Пофиксил перемешивание данных.

Сейчас выложу версию.


bobbinFile.getCanonicalPath().intern() - использование пула строк виртуальной машины не является хорошим решением - там и так их много (как минимум со слов Шипилева). А вы еще и вызываете попытку интернирования на каждую операцию.
7 авг 19, 16:54    [21943996]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch,

Согласен. Откачу.

Подумаю ещё как исправить.
7 авг 19, 16:54    [21943998]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
PetroNotC Sharp
dakeiras,
А теперь рядом минимальный с логами default.


Зачем?

Для quck start должна быть некая дефолтная конфигурация чтоб любой разработчик мог
легко интегрировать твоего Бобина в свой проект. В противном случае нужен шаблон или визард
создания Бобино-подобного проекта а это сам понимаешь - чёртов гиморр.

Причем дефолтная конфигурация должна быть компактна. Например как в log4j.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>


Что касается меня - так я ленив. Я-бы и это не писал. Но не писать совсем нельзя. Иначе аппеднеры не разберуться
куда писать. В консоль или в файл.
7 авг 19, 17:27    [21944024]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 1019
mayton
так я ленив.
прям как я)))
7 авг 19, 17:38    [21944031]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
PetroNotC Sharp
mayton
так я ленив.
прям как я)))


Третьим буду:)
7 авг 19, 17:45    [21944036]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
пропущено...


Зачем?

Для quck start должна быть некая дефолтная конфигурация чтоб любой разработчик мог
легко интегрировать твоего Бобина в свой проект. В противном случае нужен шаблон или визард
создания Бобино-подобного проекта а это сам понимаешь - чёртов гиморр.

Причем дефолтная конфигурация должна быть компактна. Например как в log4j.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>


Что касается меня - так я ленив. Я-бы и это не писал. Но не писать совсем нельзя. Иначе аппеднеры не разберуться
куда писать. В консоль или в файл.


Аа, сорян. Ты имеешь в виду стартовый конфиг Бобины.

Рад что такой вопрос, значит немного заинтересовало.

1) Бобина работает в минимуме вообще без конфига - пишет в консоль всё подряд.
2) Вот пример минимального конфига с файлом:
{
  "destinations": [
    {
      "name": "io.infinite.bobbin.destinations.FileDestination",
      "properties": {
        "fileName": "\"./LOGS/THREADS/application.log\""
      }
    },
    {
      "name": "io.infinite.bobbin.destinations.ConsoleDestination"
    }
  ]
}


3) Вот пример конфига с указанием уровней, классов и разбиением на несколько файлов и указанием формата:
{
  "levels": "['debug', 'info', 'warn', 'error', 'trace'].contains(level)",
  "classes": "className.contains('your.package.name')",
  "destinations": [
    {
      "name": "io.infinite.bobbin.destinations.FileDestination",
      "levels": "['info', 'warn', 'error', 'trace'].contains(level)",
      "classes": "className.contains('your.package.name.subpackage')",
      "properties": {
        "fileName": "\"./LOGS/${className}.log\""
      },
      "format": "\"${level}|${threadName}|${className}|${message}\\n\""
    },
    {
      "name": "io.infinite.bobbin.destinations.ConsoleDestination",
      "levels": "level=='info'"
    }
  ]
}
7 авг 19, 17:48    [21944043]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Данный rule избыточен по своей природе.
"levels": "['debug', 'info', 'warn', 'error', 'trace'].contains(level)"


На самом деле здесь достаточно одного параметра
level = ....


Все остальные - из него вытекают.
7 авг 19, 18:01    [21944048]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Это что?
"fileName": "\"./LOGS/${className}.log\""

На каждый className будет создаваться отдельный файл?
7 авг 19, 18:04    [21944050]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
mayton
Это что?
"fileName": "\"./LOGS/${className}.log\""

На каждый className будет создаваться отдельный файл?


Я бы даже уточнил, что скрывается за className? Имя логгера (LoggerFactory.getLogger(SomeClass.class)) ? Или имя вызывающего класса?
7 авг 19, 18:23    [21944069]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
Данный rule избыточен по своей природе.
"levels": "['debug', 'info', 'warn', 'error', 'trace'].contains(level)"


На самом деле здесь достаточно одного параметра
level = ....


Все остальные - из него вытекают.


Не понял мысль. Что избыточно?
7 авг 19, 18:25    [21944073]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
Это что?
"fileName": "\"./LOGS/${className}.log\""

На каждый className будет создаваться отдельный файл?


Да. Но так использовать не обязательно, это пример.
7 авг 19, 18:26    [21944074]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
mayton
Это что?
"fileName": "\"./LOGS/${className}.log\""

На каждый className будет создаваться отдельный файл?


Я бы даже уточнил, что скрывается за className? Имя логгера (LoggerFactory.getLogger(SomeClass.class)) ? Или имя вызывающего класса?


В терминологии Slf4j - имя логгера.
В терминологии Бобины - имя класса:

Конструктор Бобины:
    Bobbin(String className) {
        this.className = className
    }
7 авг 19, 18:30    [21944077]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton
Данный rule избыточен по своей природе.
"levels": "['debug', 'info', 'warn', 'error', 'trace'].contains(level)"


На самом деле здесь достаточно одного параметра
level = ....


Все остальные - из него вытекают.


Не понял мысль. Что избыточно?

Левел - это уровень. Как уровень воды в ведре. Он - один.

У тебя не может быть одновременно пол-ведра и четверть ведра.

Если логгирование грамотно спроектировано то детализация регулируется порогом чувствительности логгера.
И не должно быть попытки логгировать WARN + TRACE при этом забить болт на промежуточные уровни.
7 авг 19, 18:32    [21944080]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
Lelouch
пропущено...


Я бы даже уточнил, что скрывается за className? Имя логгера (LoggerFactory.getLogger(SomeClass.class)) ? Или имя вызывающего класса?


В терминологии Slf4j - имя логгера.
В терминологии Бобины - имя класса:

Конструктор Бобины:
    Bobbin(String className) {
        this.className = className
    }

Ты-же понимаешь что в контексте одного jvm процесса могут существовать несколько одинаковых className
в разных класслоадерах. Ты-же понимаешь что для некоторых сущностей (анонимные классы) сложно
определить className.
7 авг 19, 18:34    [21944087]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras
Lelouch
пропущено...


Я бы даже уточнил, что скрывается за className? Имя логгера (LoggerFactory.getLogger(SomeClass.class)) ? Или имя вызывающего класса?


В терминологии Slf4j - имя логгера.
В терминологии Бобины - имя класса:

Конструктор Бобины:
    Bobbin(String className) {
        this.className = className
    }


Почему не использовать общепринятую терминологию Slf4j?
7 авг 19, 18:36    [21944090]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch
dakeiras
пропущено...


В терминологии Slf4j - имя логгера.
В терминологии Бобины - имя класса:

Конструктор Бобины:
    Bobbin(String className) {
        this.className = className
    }


Почему не использовать общепринятую терминологию Slf4j?


Я принимаю API (интерфейс) Slf4j (хотя и он под вопросом - см. Google Flogger).
На этом я ограничился в основном.

Это же касается и уровней логирования:
автор
Левел - это уровень. Как уровень воды в ведре. Он - один.

У тебя не может быть одновременно пол-ведра и четверть ведра.

Если логгирование грамотно спроектировано то детализация регулируется порогом чувствительности логгера.
И не должно быть попытки логгировать WARN + TRACE при этом забить болт на промежуточные уровни.


Это ущербная философия log4j.
Один человек сделал (автор), теперь все повторяют за ним.

В Бобине всё иначе.

Вот документация:
https://github.com/INFINITE-TECHNOLOGY/BOBBIN/wiki/2---Key-Features#events

Events
In Object-oriented terms, existing logging frameworks consider log messages as events belonging to the same hierarchy:

- Trace
- Debug extends Trace
- Info extends Debug
- Warning extends Info
- Error extends Warning
This happens due to comparable nature of conventional Log Levels: e.g. Trace < Debug < Info < Warning < Error.

This is a traditional paradigm which is so old that people just take it is as something granted and immutable.

We change this paradigm.

Bobbin considers log messages as separate independent events with different types (as per their level).

With Bobbin it is possible to configure enabled logger levels in a granular way without filter, using array:

{
  "levels": "['info'].contains(level)"
}
7 авг 19, 19:02    [21944109]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
пропущено...


В терминологии Slf4j - имя логгера.
В терминологии Бобины - имя класса:

Конструктор Бобины:
    Bobbin(String className) {
        this.className = className
    }

Ты-же понимаешь что в контексте одного jvm процесса могут существовать несколько одинаковых className
в разных класслоадерах. Ты-же понимаешь что для некоторых сущностей (анонимные классы) сложно
определить className.

В 99% случаев это class name. И нет смысла его по другому называть из-за 1% случаев.
Это контр-интуитивно.
7 авг 19, 19:06    [21944110]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Нет ни одной, ни малейшей причины считать что например error это подмножество debug, как это делается во всех остальных логгеров.
Это ярчайшая наркомания, от которой волосы дыбом встают в 2019 году.
7 авг 19, 19:10    [21944112]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Lelouch,

Пофиксил смешение данных, 2.0.7.

Ещё раз огромное спасибо. Сразу видно - человек мега мозг Java.
Сходу такое увидеть. Респект нереальный.
7 авг 19, 19:17    [21944118]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
dakeiras
Lelouch,

Пофиксил смешение данных, 2.0.7.

Ещё раз огромное спасибо. Сразу видно - человек мега мозг Java.
Сходу такое увидеть. Респект нереальный.


Поправочка, 2.0.8...
7 авг 19, 19:31    [21944128]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton
пропущено...

Ты-же понимаешь что в контексте одного jvm процесса могут существовать несколько одинаковых className
в разных класслоадерах. Ты-же понимаешь что для некоторых сущностей (анонимные классы) сложно
определить className.

В 99% случаев это class name. И нет смысла его по другому называть из-за 1% случаев.
Это контр-интуитивно.

Упорство - это хорошая черта. Я уважаю упорных.

Но иногда упорство переходит в твердолобость.

Как мы объясним пользователю или кастомеру clash имен классов?
7 авг 19, 19:39    [21944132]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
vas0
Member

Откуда: Таможенный союз (Россия, Казахстан)
Сообщений: 1210
dakeiras,

Мельком глянул код например здесь,
class Bobbin extends MarkerIgnoringBase {
    String className
    List<Destination> destinations = new ArrayList<>()
    BobbinScriptEngine bobbinScriptEngine
}
У тебя же код выполняется в многопоточной среде так? А классы потоко-небезопастны. За счет чего у тебя идет согласованное чтение/запись если ты не используешь никакие примитивы синхронизации (synchronized, volatile, ReentrantLock) ?
7 авг 19, 19:41    [21944133]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
пропущено...

В 99% случаев это class name. И нет смысла его по другому называть из-за 1% случаев.
Это контр-интуитивно.

Упорство - это хорошая черта. Я уважаю упорных.

Но иногда упорство переходит в твердолобость.

Как мы объясним пользователю или кастомеру clash имен классов?

Ок, без проблем. Пусть будет Logger Name ( in most cases Class Name). Ок?
7 авг 19, 19:46    [21944134]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
vas0,

Тут вообще весь проект и всё обсуждение строится на многопоточности и как оптимизировать быстродействие синхронизации.

На текущий момент:
- Файлы в ThreadLocal, чтобы не была запись в чужой файл
- ConcurrentHashMap + ReentrantLock - чтобы в одном файле строки выводились синхронно для разных потоков

Всё остальное потокобезопасно и не требует синхронизации.
7 авг 19, 19:49    [21944135]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton
пропущено...

Упорство - это хорошая черта. Я уважаю упорных.

Но иногда упорство переходит в твердолобость.

Как мы объясним пользователю или кастомеру clash имен классов?

Ок, без проблем. Пусть будет Logger Name ( in most cases Class Name). Ок?

Да это ОК.

Был такой персонаж. Капитан Врунглель.
Он говорил - Как вы яхту назовёте - так она и поплывет.

Логгер - должен называться логгер. А никак не className. И вообще в современной JDK
не стоит завязываться на имя класса. И семантика должна быть как у логгера.
А не как у класса. Логгер - важен. Логгер может накрывать группу классов.
Имя логгера может браться откуда угодно. Он может быть динамичен. Но он не может
быть равен 1:1 с классом. Классы - сущность которой управляет класслоадер.
Логгеры - сущность которой управляем мы и бизнес.
7 авг 19, 19:52    [21944138]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
пропущено...

Ок, без проблем. Пусть будет Logger Name ( in most cases Class Name). Ок?

Да это ОК.

Был такой персонаж. Капитан Врунглель.
Он говорил - Как вы яхту назовёте - так она и поплывет.

Логгер - должен называться логгер. А никак не className. И вообще в современной JDK
не стоит завязываться на имя класса. И семантика должна быть как у логгера.
А не как у класса. Логгер - важен. Логгер может накрывать группу классов.
Имя логгера может браться откуда угодно. Он может быть динамичен. Но он не может
быть равен 1:1 с классом. Классы - сущность которой управляет класслоадер.
Логгеры - сущность которой управляем мы и бизнес.

Ок, согласен. Спасибо.

Чуть позже переименую переменную.
7 авг 19, 20:02    [21944142]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Alexey Tomin
Member

Откуда: Самара
Сообщений: 1733
dakeiras
Где я кого-то высокомерно оценивал? Можно пример или цитату мою?


А пожалуйста:
dakeiras
легкой и простой настройкой (в отличии от невменяемых настроек других логгеров)


dakeiras
По какому уровню Log4j? Совершенно не индустриальная библиотека, которая по стечению обстоятельств и отсутствия альтернатив стала популярной.
У неё совершенно упоротая концепция иерархических логгеров - абсолютно не удобная привязка к уровню логирования.
Непонятно почему нельзя было изначально сделать её нормально.


Достаточно?

dakeiras
В данном случае (как и в нескольких других в этой теме от других комментаторов) вы переходите на личности, зачем-то подразумеваете мою тупость и пр.


Вы сами первый начали.
Вообще начать тему с заявления "20 лет все фигнёй занимались а я тут пришёл и сделал намного лучше" - это подставится под сильную критику.

dakeiras
автор
То ли что не понимает, что документацию пишуют чтобы читать, а не чтобы высокомерно отвергать.

Не совсем понял, вы про какую документацию? Есть Вики, там довольно детально всё описано.
Никто ничего не отвергает.


Вам сразу указали на то, что нельзя использовать SimpleDateFormat в многопоточном коде. Что в его документации это явно написано.
Но зачем-то Вы упёрлись, что можно, что "я тестировал" (тут Шипёлёв привычно икнул).

Ну и вооще- предлагать всем библиотеку логирования, которая тащит с собой несколько мегабайт зависимостей (groovy-runtime) - это странной действо, заставляющее перейти на личность автора.
SDK это такая вещь, в которой размер имеет значение.
8 авг 19, 07:45    [21944291]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 1019
Alexey Tomin,
+1
8 авг 19, 08:56    [21944323]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Alexey Tomin,

Вы скачали Бобину? Попробуйте.
Удивитесь, насколько всё сделано лучше чем logback.

А так Ваша предвзятость обоснована уверенностью, что «всё уже изобретено» и всё новое (особенно от неизвестных авторов) - не нужно.

Советую менять настрой. Вот только краткий список проектов в Pipeline:
- Портирование BlackBox на GCLIB - автоматическое добавление логирования на этапе компиляции. Реализовано сейчас на Groovy AST и работает только с Груви кодом
- Step Up авторизационный сервер и валидация JWT без обращения к БД - при помощи regex, и настройкой доступа на авторизационном сервере (а не на сервере ресурсов) - в универсальной форме
- Универсальный CRUD GUI к HATEOAS сервисам на ReactJs

Из того что уже сделано:
- Pigeon - рассылки и push notifications (SOAP, REST)
- BlackBox - уникальный проект по автоматическому добавлению логирования с помощью аннотации (на уровнях от Ошибки с аргументами вызова, Вызова метода, Стейтментов - и до самого НИЖНЕГО уровня - expression). Работает на Груви AST API.
- Supplies - разные утилиты мелкие
Ну и сама Бобина.
8 авг 19, 11:18    [21944478]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Ну и вооще- предлагать всем библиотеку логирования, которая тащит с собой несколько мегабайт зависимостей (groovy-runtime) - это странной действо, заставляющее перейти на личность автора.
SDK это такая вещь, в которой размер имеет значение.


Место на диске чтоли кончится?))
Вы похоже из любителей битовых масок в прикладных приложениях)
8 авг 19, 11:25    [21944491]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras, по поводу скачать и попробовать. Я обещаю что когда-нибудь попробую.
Но до того как попробовать я обычно пытаюсь понять каково "прендазначение" вещи.
Например. Предназначение жопы - чтобы испражняться. Хотя есть некоторые
любители странного секса которые хотят погрузить в чью-то жопу свой крайний
отросток. И когда например мен на code-review приносят константы завёрнутые
в java interface - я просто спрашиваю. Ты что - любишь совокупляться в жопу?

Понятно да?

Предназначение. Ты должен сообществу объяснить предназначение твоей библиотеки.
Про BlackBox можешь даже не рассказывать. Форум не знает что это такое и никому
не интересны твои тестерские практики. Плевать на блек бокс. У нас - другие задачи.

Далее. По поводу Толстого Бобина.

И какую идею закладывал туда автор. Или какую философию. Обычно зрелость
продукта определяется этим. Например Log4j2 в режиме Async использует (косвенно)
зависимость от библиотеки неблокирующих очередей disruptor. Эта библиотечка
буферизирует не дисковый трафик а именно события. Events. Вот такая вот идея.
Хотя возможность асинхронной записи в файл тоже поддерживается но это другая
настройка.

За кадром остался вопрос перформанса. Ты так и не предоставил сообществу никаких
бенчмарков. Я по прежнему убёжден что Groovy генерирует самый медленный код
(для интенсивных вычислений) и никто меня не убедил в обратном. Грубо говоря
в линейке Java/Kotlin/Scala/Groovy, последний занимает последнее место. Груви - медленный
покемон в этом списке. И ты выкатил на общий суд тайм-критичную библиотеку взяв
за основу самый медленный компиллятор.
8 авг 19, 11:45    [21944516]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Valentin Kolesnikov
Member

Откуда:
Сообщений: 3186
Может вам будет полезен метод U.format(string, .. args) в библиотеке из соседней ветки.

20531307

Хорошего Вам дня!
8 авг 19, 12:01    [21944538]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Alexey Tomin
Member

Откуда: Самара
Сообщений: 1733
dakeiras
Вы скачали Бобину? Попробуйте.


Я вроде уже объяснил причину, почему не буду это делать.

dakeiras
Удивитесь, насколько всё сделано лучше чем logback.


У меня код очень многопоточный, с высоким требованием к производительности. После SimpleDateFormat дальше читать не интересно- если есть столь очевидная бага- зачем искать другие? Конкаренси баги могут стрелять очень редко и ОЧЕНЬ больно. Мне наших баг хватает. logback работает быстро и надёжно.

dakeiras
А так Ваша предвзятость обоснована уверенностью, что «всё уже изобретено» и всё новое (особенно от неизвестных авторов) - не нужно.


Нет.
Чтобы изобрести что-то хорошее, надо сначала понять то, что сделали предшественники.
Для тестов использовать JMH например. И показывать преимущество в виде конкретных тестов, которые каждый может запустить и получить результат.

Показать преимущество настройки в виде примеров, а не просто слов.

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

dakeiras
- BlackBox - уникальный проект по автоматическому добавлению логирования с помощью аннотации (на уровнях от Ошибки с аргументами вызова, Вызова метода, Стейтментов - и до самого НИЖНЕГО уровня - expression).


Я тут думаю, как очень нужную либу перевести с кодогенерации при компиляции на лямбды- потому что "добавление кода в компиляции"- это добавление проблем в отладке.
8 авг 19, 12:28    [21944565]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Давайте здесь не обсуждать производительность Груви.
Это оффтопик.
Можно отдельную тему сделать. Если в кратце - Вы заблуждаетесь, это опять же МИФ, основанный на ОООЧЕНЬ ранних версиях (более 8 лет назад). Ещё раз повторю что используется @CompileStatic во всех классах Бобины, так что он даёт просто обычный Java код.
8 авг 19, 13:00    [21944613]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Я уже даже приводил пример декомпилированного класса в этой теме, если охота - можно посмотреть и убедиться.
8 авг 19, 13:01    [21944614]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
После SimpleDateFormat дальше читать не интересно- если есть столь очевидная бага- зачем искать другие

Мой богатый опыт подсказывает что что-то очевидно только при поверхностном ознакомлении.

Изначально ВСЕ экземпляры класса Bobbin были в ThreadLocal.
Так что не было это микроскопической баги с SimpleDateFormat.

Потом дизайн поменяли, и это стало актуально. Уже исправлено.
8 авг 19, 13:06    [21944623]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
Ты должен сообществу объяснить предназначение твоей библиотеки.
Про BlackBox можешь даже не рассказывать. Форум не знает что это такое и никому
не интересны твои тестерские практики. Плевать на блек бокс. У нас - другие задачи.

Далее. По поводу Толстого Бобина.

И какую идею закладывал туда автор. Или какую философию. Обычно зрелость
продукта определяется этим. Например Log4j2 в режиме Async использует (косвенно)
зависимость от библиотеки неблокирующих очередей disruptor. Эта библиотечка
буферизирует не дисковый трафик а именно события. Events. Вот такая вот идея.
Хотя возможность асинхронной записи в файл тоже поддерживается но это другая
настройка.

За кадром остался вопрос перформанса. Ты так и не предоставил сообществу никаких
бенчмарков. Я по прежнему убёжден что Groovy генерирует самый медленный код
(для интенсивных вычислений) и никто меня не убедил в обратном. Грубо говоря
в линейке Java/Kotlin/Scala/Groovy, последний занимает последнее место. Груви - медленный
покемон в этом списке. И ты выкатил на общий суд тайм-критичную библиотеку взяв
за основу самый медленный компиллятор.


Из readme.md:

автор
Bobbin is a high-performance Groovy Slf4j-compatible logger designed for multi-threaded applications (especially those with persistent threads like batch and messaging applications).

Bobbin leverages the concept of Logback/Log4j2 sifting appenders while providing much more easier configuration using native Groovy/Java scripting expressions.


https://github.com/INFINITE-TECHNOLOGY/BOBBIN

Из Вики:

автор
Bobbin creates multiple isolated log files using a simple JSON configuration supporting Groovy Scripts to compute file names and other dynamic parameters during run-time.

Some of the File name segregation criteria include:

- Thread Name
- - Thread Group Name
- Class Name
- Log level
- MDC values
- Date
- Any other run-time parameters and their combinations
Bobbin leverages the concept of Logback/Log4j2 sifting appenders while providing much more easier configuration using native Groovy/Java scripting expressions.

Bobbin is high-performance logger optimized to be used in heavy load multi-threaded environments (with hundreds of persistent threads - especially those with persistent threads like batch and messaging applications).

It's CPU, GC and RAM footprint has been tuned to work as a primary logger within Spring stack, including Web context and JPA.


https://github.com/INFINITE-TECHNOLOGY/BOBBIN/wiki

Не хотел этого говорить, но "не читал, но осуждаю"...

Насчёт Бенчмарка: будет в течении 3-4 дней:
- Однопоточная работа в 1 файл
- Однопоточная работа в много файлов
- Многопоточная в 1 файл
- Многопоточная в много файлов со смешиванием потоков
- Многопоточная в много файлов без смешивания потоков (1 поток на файл)

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

Вот и причина Вашей предвзятости.
В своё время лень было изучить - значит "не понравилась идея".

Как тут написали, люди 10 лет делали Груви, а тут такой кадр нарисовался - и ему идея не нравится.
Зато появился котлин - сразу всем понравилось :) Потому что он продвинут при нечестной конкуренции.
И не поддерживает и половины функционала Груви.

автор
Для тестов использовать JMH например. И показывать преимущество в виде конкретных тестов, которые каждый может запустить и получить результат.

Спасибо за инфо, изучу и возможно использую.

автор
Я тут думаю, как очень нужную либу перевести с кодогенерации при компиляции на лямбды- потому что "добавление кода в компиляции"- это добавление проблем в отладке.

Зато лямбды это легко отлаживать.
8 авг 19, 13:17    [21944639]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Мы все ждем тестов с @Jmh.

Нужно убедительное доказательство перформанса. Иначе - это не интересно.
8 авг 19, 13:18    [21944641]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Валентин Колесников,

автор
Может вам будет полезен метод U.format(string, .. args) в библиотеке из соседней ветки.

20531307

Хорошего Вам дня!


Мощь. Обязательно изучу.
Уже сейчас её можно использовать с Бобиной, добавив в билд - и настроив format в Bobbin.json:

"format": "U.format(\"DateTime = {} Message = {}\", dateTime, message)",
8 авг 19, 13:22    [21944647]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
Мы все ждем тестов с @Jmh.

Нужно убедительное доказательство перформанса. Иначе - это не интересно.


Оки. Скоро будет бенчмарк.
8 авг 19, 13:22    [21944648]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Alexey Tomin
Member

Откуда: Самара
Сообщений: 1733
dakeiras
- Многопоточная в 1 файл
- Многопоточная в много файлов со смешиванием потоков


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

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

Вот и причина Вашей предвзятости.
В своё время лень было изучить - значит "не понравилась идея".


Да я писал даже на нём. Работало. Для примитивных проектов типа UI пойдёт. Писать многопоточную математику- ад.

dakeiras
Как тут написали, люди 10 лет делали Груви, а тут такой кадр нарисовался - и ему идея не нравится.


Вы не понимаете разницы между "мне не нравится" и "Совершенно не индустриальная библиотека, которая по стечению обстоятельств и отсутствия альтернатив стала популярной.", "в отличии от невменяемых настроек других логгеров" и свежего перла "продвинут при нечестной конкуренции"?

dakeiras
Зато появился котлин - сразу всем понравилось :) Потому что он продвинут при нечестной конкуренции.
И не поддерживает и половины функционала Груви.


Понравился он далеко не всем и не сразу. Кто-то дальше любит scala, кто-то ceylon, кто-то groovy. Каждому своё.
А про "нечестную конкуренцию"- вот это интересно- расскажите, пожалуйста.

dakeiras
автор
Я тут думаю, как очень нужную либу перевести с кодогенерации при компиляции на лямбды- потому что "добавление кода в компиляции"- это добавление проблем в отладке.

Зато лямбды это легко отлаживать.


Я дебажил и грувивскую "магию", и самописную кодогенерацию и лямбды.
Можете верить, можете нет- но лямбды дебажить проще всего.
Особенно "прелестно" втыкать в ошибки самописного мавен-плагина. Вот у нас в 5% билдов почему-то падает с безумным стектрейсом- я даже браться за это не хочу...
8 авг 19, 13:39    [21944671]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
А про "нечестную конкуренцию"- вот это интересно- расскажите, пожалуйста.


Элементарно. Забашляли Гуглу чтобы Идею протолкнуть в Android Studio и далее - забашляли чтобы сделать Котлин офиц. языком для Android.

Котлин вообще появился без надобности, нет у него use case.
8 авг 19, 13:46    [21944679]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
я уже молчу, что сама Intellij Idea застряла по функционалу в 2000х.

Не могут до сих пор нормальную поддержку Gradle сделать.
8 авг 19, 13:50    [21944682]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Alexey Tomin
Member

Откуда: Самара
Сообщений: 1733
dakeiras
автор
А про "нечестную конкуренцию"- вот это интересно- расскажите, пожалуйста.


Элементарно. Забашляли Гуглу чтобы Идею протолкнуть в Android Studio и далее - забашляли чтобы сделать Котлин офиц. языком для Android.


Бред какой.
IDEA сдала Android Studio потому что работники гугла пользовуются перешли на IDEA. Вот и всё.
У них вообще в разработки порядка особо нет и деньги не сделали бы ничего.
Поддержали котлин в андроид потому что решили, что это хорошо для андроид и всё.

dakeiras
Котлин вообще появился без надобности, нет у него use case.


Бреслав прямым текстом говорил, что цели создания котлина (в порядке его приоритетов):
- потому что это интересно
- у фирмы достаточно денег, чтобы выделить работников для разработки неведомой фигни с нулевой одходностью
- они хотели поднять свой статус как фирмы
- на java писать надоело и непродуктивно, а scala/groovy не вызывали энтузиазма.
8 авг 19, 13:51    [21944684]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Сборщиков много. И среда вовсе не обязана поддержать их всех на 100%.

Понимаете да? Это не ее ответственность поддерживать всех и вся. Иначе стоимость
техподдержки превысит вообще прибыль от существования проекта.
8 авг 19, 13:54    [21944686]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
Сборщиков много. И среда вовсе не обязана поддержать их всех на 100%.

Понимаете да? Это не ее ответственность поддерживать всех и вся. Иначе стоимость
техподдержки превысит вообще прибыль от существования проекта.


Это смешно.

Есть 2 сборщика: Maven и Gradle.

И среда:
1) Обязана их поддерживать
2) В 2019 НЕ должна изобретать свою сборку ("проект\модули")

Иначе такая среда не нужна. Есть индустриальный стандарт в Java.
8 авг 19, 13:57    [21944689]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Alexey Tomin
dakeiras
пропущено...


Элементарно. Забашляли Гуглу чтобы Идею протолкнуть в Android Studio и далее - забашляли чтобы сделать Котлин офиц. языком для Android.


Бред какой.
IDEA сдала Android Studio потому что работники гугла пользовуются перешли на IDEA. Вот и всё.
У них вообще в разработки порядка особо нет и деньги не сделали бы ничего.
Поддержали котлин в андроид потому что решили, что это хорошо для андроид и всё.

dakeiras
Котлин вообще появился без надобности, нет у него use case.


Бреслав прямым текстом говорил, что цели создания котлина (в порядке его приоритетов):
- потому что это интересно
- у фирмы достаточно денег, чтобы выделить работников для разработки неведомой фигни с нулевой одходностью
- они хотели поднять свой статус как фирмы
- на java писать надоело и непродуктивно, а scala/groovy не вызывали энтузиазма.


Вы просто подтвердили мои слова.

Тут есть ещё момент - суды между Oracle и Google касательно Java в Android.
Но Гугл должен был выбрать Груви, а не котлин.
8 авг 19, 13:59    [21944694]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton
Сборщиков много. И среда вовсе не обязана поддержать их всех на 100%.

Понимаете да? Это не ее ответственность поддерживать всех и вся. Иначе стоимость
техподдержки превысит вообще прибыль от существования проекта.


Это смешно.

Есть 2 сборщика: Maven и Gradle.

И среда:
1) Обязана их поддерживать
2) В 2019 НЕ должна изобретать свою сборку ("проект\модули")

Иначе такая среда не нужна. Есть индустриальный стандарт в Java.

Я sbt пользуюсь. И он хреново поддерживается. Что мне делать?
8 авг 19, 14:02    [21944697]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
Тут есть ещё момент - суды между Oracle и Google касательно Java в Android.
Но Гугл должен был выбрать Груви, а не котлин.

Зачем ты в технический топик затаскиваешь суды крупных контор?
Это вообще никаким боком не имеет отношения к теме топика.

Обсуждаем Толстого Робина-Бобина.
8 авг 19, 14:04    [21944699]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
пропущено...


Это смешно.

Есть 2 сборщика: Maven и Gradle.

И среда:
1) Обязана их поддерживать
2) В 2019 НЕ должна изобретать свою сборку ("проект\модули")

Иначе такая среда не нужна. Есть индустриальный стандарт в Java.

Я sbt пользуюсь. И он хреново поддерживается. Что мне делать?


Ничего не сделать. А стоит Идея конски в месяц.
8 авг 19, 14:04    [21944700]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
Тут есть ещё момент - суды между Oracle и Google касательно Java в Android.
Но Гугл должен был выбрать Груви, а не котлин.

Зачем ты в технический топик затаскиваешь суды крупных контор?
Это вообще никаким боком не имеет отношения к теме топика.

Обсуждаем Толстого Робина-Бобина.


Оки.
8 авг 19, 14:04    [21944701]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Alexey Tomin
Member

Откуда: Самара
Сообщений: 1733
Alexey Tomin,

Кстати, посмотрел код и возникли вопросы:
1. В FileDestination в 100-поточном коде будет создано 100 объектов типа "файл" для одного (реального) файла. Зачем это надо? Не говоря уже про расход памяти- зачем?
2. За счёт чего Ваш код должен быть быстрее logback? Какие проблемы Вы в нём нашли?
8 авг 19, 14:11    [21944711]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Alexey Tomin
Member

Откуда: Самара
Сообщений: 1733
dakeiras
Есть 2 сборщика: Maven и Gradle.

И среда:
1) Обязана их поддерживать
2) В 2019 НЕ должна изобретать свою сборку ("проект\модули")

Иначе такая среда не нужна. Есть индустриальный стандарт в Java.


1. А как же Bazel?
2. Каким образом среда оказалась Вам должна?
8 авг 19, 14:12    [21944714]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Alexey Tomin
Member

Откуда: Самара
Сообщений: 1733
dakeiras
Но Гугл должен был выбрать Груви, а не котлин.


Опять "должен". Когда это Гугл задолжал Вам?
Они выбрали то, что считали лучшим. Не согласны- Ваше право.
8 авг 19, 14:13    [21944715]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Alexey Tomin
Member

Откуда: Самара
Сообщений: 1733
dakeiras
я уже молчу, что сама Intellij Idea застряла по функционалу в 2000х.

Не могут до сих пор нормальную поддержку Gradle сделать.


1. А кто обогнал IDEA? Что сильно лучше?
2. По поводу поддержки gradle. Вы просто, видимо, не делали подобные вещи.

Несложно "разобрать" maven-проект (хотя наши бойцы сумели тут удивить IDEA - не каждая версия может собрать наши проекты- но это просто от зуда от шила в ж..е). В вот gradle - это не метаинформация, это набор команд. И чтобы нормально его поддержать- надо понять, что автор сего думал. Это очень сложная задача.
Хотите сделать лучше? Ну так сделайте.
8 авг 19, 14:17    [21944726]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Alexey Tomin
dakeiras
Есть 2 сборщика: Maven и Gradle.

И среда:
1) Обязана их поддерживать
2) В 2019 НЕ должна изобретать свою сборку ("проект\модули")

Иначе такая среда не нужна. Есть индустриальный стандарт в Java.


1. А как же Bazel?
2. Каким образом среда оказалась Вам должна?


Я бабло за неё башляю, каждые 3 месяца. Притом дорого стоит.
8 авг 19, 14:22    [21944743]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Alexey Tomin
Alexey Tomin,

Кстати, посмотрел код и возникли вопросы:
1. В FileDestination в 100-поточном коде будет создано 100 объектов типа "файл" для одного (реального) файла. Зачем это надо? Не говоря уже про расход памяти- зачем?
2. За счёт чего Ваш код должен быть быстрее logback? Какие проблемы Вы в нём нашли?


Как минимум за счёт отсутствия волшебного синтаксиса "форматирования" сообщения.
8 авг 19, 14:23    [21944746]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Alexey Tomin
dakeiras
я уже молчу, что сама Intellij Idea застряла по функционалу в 2000х.

Не могут до сих пор нормальную поддержку Gradle сделать.


1. А кто обогнал IDEA? Что сильно лучше?
2. По поводу поддержки gradle. Вы просто, видимо, не делали подобные вещи.

Несложно "разобрать" maven-проект (хотя наши бойцы сумели тут удивить IDEA - не каждая версия может собрать наши проекты- но это просто от зуда от шила в ж..е). В вот gradle - это не метаинформация, это набор команд. И чтобы нормально его поддержать- надо понять, что автор сего думал. Это очень сложная задача.
Хотите сделать лучше? Ну так сделайте.


Они и тут нечестную конкуренцию используют - kotlin dsl нормально поддерживается в Идее, а вот Груви - нет.
8 авг 19, 14:25    [21944754]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
dakeiras
Alexey Tomin
пропущено...


1. А кто обогнал IDEA? Что сильно лучше?
2. По поводу поддержки gradle. Вы просто, видимо, не делали подобные вещи.

Несложно "разобрать" maven-проект (хотя наши бойцы сумели тут удивить IDEA - не каждая версия может собрать наши проекты- но это просто от зуда от шила в ж..е). В вот gradle - это не метаинформация, это набор команд. И чтобы нормально его поддержать- надо понять, что автор сего думал. Это очень сложная задача.
Хотите сделать лучше? Ну так сделайте.


Они и тут нечестную конкуренцию используют - kotlin dsl нормально поддерживается в Идее, а вот Груви - нет.


я имею в виду gradle dsl
8 авг 19, 14:25    [21944756]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
Alexey Tomin
пропущено...


1. А кто обогнал IDEA? Что сильно лучше?
2. По поводу поддержки gradle. Вы просто, видимо, не делали подобные вещи.

Несложно "разобрать" maven-проект (хотя наши бойцы сумели тут удивить IDEA - не каждая версия может собрать наши проекты- но это просто от зуда от шила в ж..е). В вот gradle - это не метаинформация, это набор команд. И чтобы нормально его поддержать- надо понять, что автор сего думал. Это очень сложная задача.
Хотите сделать лучше? Ну так сделайте.


Они и тут нечестную конкуренцию используют - kotlin dsl нормально поддерживается в Идее, а вот Груви - нет.

Ну Kotlin это их собственная разработка.

Представь что я пожаловался что iPhone не поддерживает зарядки от Xiaomi. А должен?
8 авг 19, 14:44    [21944806]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
пропущено...


Они и тут нечестную конкуренцию используют - kotlin dsl нормально поддерживается в Идее, а вот Груви - нет.

Ну Kotlin это их собственная разработка.

Представь что я пожаловался что iPhone не поддерживает зарядки от Xiaomi. А должен?


эээээ, да.
8 авг 19, 14:55    [21944838]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
betelgeizex
Member

Откуда:
Сообщений: 70
dakeiras,

Groovy - по определению медленный язык, даже с CompileStatic.
Вот идиоматичный код на груви (компилируется и выполняется успешно):

@CompileStatic
class Test1 {

    static void main(String[] args) {
        if (!args) {
            println("error")
        }
        // TODO
    }
}


После декомпиляции получаю вот это:

  public static void main(String... args) {
        if (!DefaultTypeTransformation.booleanUnbox(args)) {
            DefaultGroovyMethods.println(Test1.class, "error");
            Object var10000 = null;
        }

  }


Спускаюсь по коду DefaultTypeTransformation.booleanUnbox, и в итоге вижу вот это:

        // if the object is not null and no Boolean, try to call an asBoolean() method on the object
        return (Boolean) InvokerHelper.invokeMethod(object, "asBoolean", InvokerHelper.EMPTY_ARGS);


Можете сами проверить. В стандартной библиотеке рефлексия везде! Какая тут производительность?
8 авг 19, 14:58    [21944841]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Alexey Tomin
Member

Откуда: Самара
Сообщений: 1733
dakeiras
Alexey Tomin
2. За счёт чего Ваш код должен быть быстрее logback? Какие проблемы Вы в нём нашли?

Как минимум за счёт отсутствия волшебного синтаксиса "форматирования" сообщения.


Это про что конкретно? Если есть поддержка SLF4J то это тоже есть. А у Вас вроде есть.

dakeiras
Они и тут нечестную конкуренцию используют - kotlin dsl нормально поддерживается в Идее, а вот Груви - нет.


Я писал компилятор, несколько раз.
И понимаю, что поддержку kotlin DSL сделать в разы проще, чем грэдла/груви.

Вообще Kotlin мне нравится тем, что я понимаю, как это в кишочках всё работает. Это вообще кайф- понимать внутренности. Больше был только когда Module2 изучал- но он намного проще.
Особенно когда представляешь, какого разбирать тот же groovy или (чур меня, чур) С (С++ даже пытаюсь- мозг взорвётся).
8 авг 19, 14:58    [21944844]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Alexey Tomin,

автор
Можете сами проверить. В стандартной библиотеке рефлексия везде! Какая тут производительность?


Так в 2006м году считалось, что рефлексия медленная.
8 авг 19, 15:21    [21944873]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
Alexey Tomin,

автор
Можете сами проверить. В стандартной библиотеке рефлексия везде! Какая тут производительность?


Так в 2006м году считалось, что рефлексия медленная.

А что случилось с 2006 года?
8 авг 19, 15:39    [21944901]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
Alexey Tomin,

пропущено...


Так в 2006м году считалось, что рефлексия медленная.

А что случилось с 2006 года?


https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/enhancements.html#a1.4
8 авг 19, 16:53    [21944986]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton
пропущено...

А что случилось с 2006 года?


https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/enhancements.html#a1.4

Дорогой друг. Можно попросить тебя не разговаривать ссылками.
В противном случае у нас разговор получается ниочем. Ты мне дал ссылку где нет цифр.
И нет оценки пользы или вреда от рефлексии или ее использования или не использования.
Мы не знаем сколько тактов CPU стоит рефлексия. И похоже ты, не знаешь как Groovy
работает с типизаций.

Поэтому. Будь добр. Разворачивай свою мысль. И у нас получится диалог.
8 авг 19, 17:06    [21944992]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
betelgeizex
Member

Откуда:
Сообщений: 70
dakeiras
mayton
пропущено...

А что случилось с 2006 года?


https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/enhancements.html#a1.4


https://docs.oracle.com/javase/tutorial/reflect/index.html

автор
The Java Tutorials have been written for JDK 8.
...
reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.
8 авг 19, 17:19    [21945004]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
dakeiras
пропущено...


https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/enhancements.html#a1.4

Дорогой друг. Можно попросить тебя не разговаривать ссылками.
В противном случае у нас разговор получается ниочем. Ты мне дал ссылку где нет цифр.
И нет оценки пользы или вреда от рефлексии или ее использования или не использования.
Мы не знаем сколько тактов CPU стоит рефлексия. И похоже ты, не знаешь как Groovy
работает с типизаций.

Поэтому. Будь добр. Разворачивай свою мысль. И у нас получится диалог.

Вы спросили, что изменилось - я ответил. Оптимизировали рефлексию, она перестала "тормозить".
В Java рефлексия одна из основных фич. Без неё Java вообще не нужна.

Если не нравится рефлексия - пишите на C.
8 авг 19, 17:21    [21945005]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.




Система управления игрушечной машиной в реальном времени.

Аппаратная платформа: Raspberri Pi 2
Программная платформа: Groovy
Перефeрия: Bluetooth джойстик от PS3, Linux драйвера джойстика и bluetooth, Java драйвер джойстика.

Я кстати собираюсь софт для полётного контроллера написать на Груви в скором времени.
Такие же адепты как вы говорят - надо C обязательно использовать, ИНАЧЕ ОНА УПАДЁТ ЗАВИСНЕТ ЗАТОРМОЗИТ.

Мне смешно от этого всего.
8 авг 19, 17:27    [21945009]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
забыл добавить, управляющую программу на Groovy написал и придумал я.
Это была первая в МИРЕ управляющая программа для ровера на Груви.

Она опрашивала джойстик и управляла PWM драйверами через i2c.
8 авг 19, 17:30    [21945012]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
и там использовалась система логирования - предвестник Bobbin.
8 авг 19, 17:32    [21945013]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
вадя
Member

Откуда: Екатеринбург
Сообщений: 16055
mayton
А что случилось с 2006 года?
тут уже показывали кино с что такое современная рефлексия, и не однократно. там чел на примерах показывал время срабатывания.
современная рефлексия очень даже быстрая.
8 авг 19, 17:42    [21945019]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
вадя
mayton
А что случилось с 2006 года?
тут уже показывали кино с что такое современная рефлексия, и не однократно. там чел на примерах показывал время срабатывания.
современная рефлексия очень даже быстрая.

И на рендеринге 3D-графики тоже быстрая?
8 авг 19, 18:35    [21945077]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
вадя
пропущено...
тут уже показывали кино с что такое современная рефлексия, и не однократно. там чел на примерах показывал время срабатывания.
современная рефлексия очень даже быстрая.

И на рендеринге 3D-графики тоже быстрая?

А зачем Вы делаете на Java программный 3d рендеринг? Это токсикомания.
8 авг 19, 18:52    [21945095]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
вадя
mayton
А что случилось с 2006 года?
тут уже показывали кино с что такое современная рефлексия, и не однократно. там чел на примерах показывал время срабатывания.
современная рефлексия очень даже быстрая.


Вы случайно с MethodHandles не путаете?
8 авг 19, 18:57    [21945096]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Alexey Tomin
Member

Откуда: Самара
Сообщений: 1733
betelgeizex
dakeiras,

Groovy - по определению медленный язык, даже с CompileStatic.
Вот идиоматичный код на груви (компилируется и выполняется успешно):

@CompileStatic
class Test1 {

    static void main(String[] args) {
        if (!args) {
            println("error")
        }
        // TODO
    }
}



А какой смысл этого кода?
args.length == 0?
args == null?
Зачем так писать?
8 авг 19, 19:39    [21945117]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
вадя
Member

Откуда: Екатеринбург
Сообщений: 16055
mayton
И на рендеринге 3D-графики тоже быстрая?
это к чему?
8 авг 19, 19:46    [21945122]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
вадя
Member

Откуда: Екатеринбург
Сообщений: 16055
Lelouch
Вы случайно с MethodHandles не путаете?
нет, там выступление именно про ревлексию
8 авг 19, 19:47    [21945123]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
вадя
Member

Откуда: Екатеринбург
Сообщений: 16055
Lelouch
Вы случайно с MethodHandles не путаете?
&feature=youtu.be
8 авг 19, 19:52    [21945128]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
mayton
пропущено...

И на рендеринге 3D-графики тоже быстрая?

А зачем Вы делаете на Java программный 3d рендеринг? Это токсикомания.

Я надеюсь что в части творческих экспериментов мы с вами лежим на одной полочке.
Ведь % использований вашего фреймворка равен нулю. Разумеется я не считаю вас самого.

По поводу оценки эффективности того или иного компиллятора. Обычно берут какой-то
численный метод и замеряют эффективность либо в количестве операций которые выполнились
за единицу времени либо оценивают период (милисекундах или мкс) одной операции.

Операции I/O обычно не рассматривают в качестве оси измерений т.к. тут в основном
работает контекст операционной системы и ваше приложение просто стоит на паузе
либо ожидает асинк-колл от финала этой операции.

У вас есть на примете какой-то численный метод или любая бизнес-логика которая достаточно
длительное время нагружает процессор и память без взаимодействия с I/O ?

И эта логика должна быть написана на Groovy.
8 авг 19, 22:17    [21945210]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
вадя,

Спасибо.
9 авг 19, 15:41    [21945727]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras,

А почему вы используете именно Groovy?
Какие преимущества перед Java кроме динамической типизации (которую вы не используете). До сих пор даже поддержки lambda из java 8 нет (в стабильной ветке).
9 авг 19, 15:52    [21945740]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Есть когнитивный парадокс. Когда человек теряет ключи на тёмной улице. Он подходит
к ближайшему фонарю и начинает искать там.

Я рискну предположить что просто господин топик-стартер хоршо знает Groovy и целенаправленно
выбрал его для разработки библиотеки. Просто такова человеческая природа.
9 авг 19, 16:22    [21945767]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
mayton
Есть когнитивный парадокс. Когда человек теряет ключи на тёмной улице. Он подходит
к ближайшему фонарю и начинает искать там.

Я рискну предположить что просто господин топик-стартер хоршо знает Groovy и целенаправленно
выбрал его для разработки библиотеки. Просто такова человеческая природа.

ну «хорошо» это громко конечно сказано:) Но чуть глубже обычного знаю, т.к. сделал проект на AST API в нём (BlackBox) - метапрограммирование, заставляет поизучать саму платформу...

Касательно самого языка - у него есть 4 могучие фичи:
1) Runtime компиляция
2) Closures
3) Динамическое добавление полей и методов в существующие классы (например Exception.isAlreadyLogged)
4) AST API

Ещё сам SDK даёт кучу полезного например @ToString,Sql builder, Json Slurper и проч.
Также неплохая вещь с синтетическими полями и getters/setters.
Traits - для множественного наследования.
Ну и синтаксис: :? in и прочее.

Ещё он может использоваться как процедурная Java, например PL/SQL программистами.
9 авг 19, 17:37    [21945829]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
Касательно самого языка - у него есть 4 могучие фичи:
1) Runtime компиляция

Рантайм компилляция была во времена самых ранних JSP/Servlets. Этим никого не удивишь.
Но кроме рантаймовости этот процесс вносит множество почти нерешаемых задач безопасности.
А именно - как защитить сервер приложений от потенциального злоумышленника если он
каким-то образом завладел контекстом рандайм компилляции.

Поэтому сама по себе постановка рантайма не полная без обсуждения того как вокруг
этого выстроить кучу баръеров безопасности. В каких песочницах запускать и какие права
выдавать.

Какое-то время мы работали с одним европейским банком и кастомер выставил нам самые жесткие
требования касающиеся пользовательского ввода. Это касалось не только SQL-инжекции.
Это самое первое что мы фиксили. Любой. Вообще самый любой пользовательский ввод
в формочку должен был рассматриваться пристально как угроза.

Как фильтровать пользовательский ввод чтобы защитить груви машину от исполнения
чего-то выше ваших привелегий в системе - я не знаю. Возможно вы знаете.

Вобщем опасная эта штука динамика в компилляции. Сложно доказать ее безопаснсоть.
9 авг 19, 18:06    [21945841]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
3) Динамическое добавление полей и методов в существующие классы (например Exception.isAlreadyLogged)

Тут ничего не могу сказать. Кроме того что это нарушает классическое SOLID.
Особенно в части Open/Closed, Liskov subst. e.t.c.
9 авг 19, 18:09    [21945843]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
dakeiras
4) AST API

Здесь я даю +1. Это хорошо. Но это хорошо изначально для других языков где AST был просто
частью исполнительной системы как было задумано. В лиспах он смотрится органично. Возможно в Erlang.
9 авг 19, 18:11    [21945846]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
автор
Рантайм компилляция была во времена самых ранних JSP/Servlets. Этим никого не удивишь.
Но кроме рантаймовости этот процесс вносит множество почти нерешаемых задач безопасности.
А именно - как защитить сервер приложений от потенциального злоумышленника если он
каким-то образом завладел контекстом рандайм компилляции.

Поэтому сама по себе постановка рантайма не полная без обсуждения того как вокруг
этого выстроить кучу баръеров безопасности. В каких песочницах запускать и какие права
выдавать.

Какое-то время мы работали с одним европейским банком и кастомер выставил нам самые жесткие
требования касающиеся пользовательского ввода. Это касалось не только SQL-инжекции.
Это самое первое что мы фиксили. Любой. Вообще самый любой пользовательский ввод
в формочку должен был рассматриваться пристально как угроза.

Как фильтровать пользовательский ввод чтобы защитить груви машину от исполнения
чего-то выше ваших привелегий в системе - я не знаю. Возможно вы знаете.

Вобщем опасная эта штука динамика в компилляции. Сложно доказать ее безопаснсоть.

У вас фундаментально неверные представления касательно безопасности приложений.
То что вы написали - это вольные фантазии школьника в перемешку с гордостью работы на ыуропэйскый банк.
Особенно порадовало про "контекст рантайм компиляции".
Хорошо что не аутофиляции. @Autowired RuntimeCompilationContext блеядь.
Press H to hack database.

Ваш эуропэйскый (косовский чтоле?) банк не требовал случайно, чтобы HTTPS использовалось?

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

Кстати от "динамики в компиляции" отлично помогают перфокарты - хер поменяешь!

Песочницы. Прямо как в Android. Наверно сложная архитектура подразумевается, с docker и прочая.
Весь пост это просто пёрл сплошной.
11 авг 19, 04:33    [21946323]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
JSR223 просто плачет в печали. Хуже динамической компиляции и reflection оказалась только runtime компиляция.

Надеюсь вы его выключили сразу (кстати интересно, можно ли его выключить).

Это отличная стратегия для троллинга - на Java форуме доказывать что ВСЕ отличия Java от C++ тормозят и небезопасны и пользователи нипаймут (ну если пишем для тупых юзеров - то да, но они и всё остальное не поймут)

Самое печальное что в реальной жизни (на работе) такие люди делают тоже самое.
11 авг 19, 05:58    [21946329]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
dakeiras
Member

Откуда:
Сообщений: 294
Если тут это кому-либо интересно, Бобина теперь и в Maven Central.

    <dependencies>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.5.4</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>io.i-t</groupId>
            <artifactId>bobbin</artifactId>
            <version>2.0.10</version>
        </dependency>
    </dependencies>


Это было сделано по просьбам нескольких больших корпораций начинающих использовать Бобину, т.к. они используют зеркало Maven Central и у них нет JCenter. Потом детально изучу их юз кейс и сделаю обзор.

А некоторые комментаторы пусть продолжают думать что они самые умные на свете и всё знают.
13 авг 19, 05:11    [21947633]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Корпораций?
13 авг 19, 07:56    [21947650]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
mayton
Корпораций?


Google, Apple и Oracle.
И даже Тим Кук сказал «It’s a revolution, Mayton»
13 авг 19, 09:30    [21947698]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1760
dakeiras
Если тут это кому-либо интересно, Бобина теперь и в Maven Central.

    <dependencies>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.5.4</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>io.i-t</groupId>
            <artifactId>bobbin</artifactId>
            <version>2.0.10</version>
        </dependency>
    </dependencies>


Это было сделано по просьбам нескольких больших корпораций начинающих использовать Бобину, т.к. они используют зеркало Maven Central и у них нет JCenter. Потом детально изучу их юз кейс и сделаю обзор.

А некоторые комментаторы пусть продолжают думать что они самые умные на свете и всё знают.


Кстати, что помешало сделать groovy зависимостью bobbin? Чтобы не приходилось добавлять в зависимости и то и то.
13 авг 19, 09:35    [21947705]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
betelgeizex
Member

Откуда:
Сообщений: 70
Lelouch
dakeiras
Если тут это кому-либо интересно, Бобина теперь и в Maven Central.

...

Это было сделано по просьбам нескольких больших корпораций начинающих использовать Бобину, т.к. они используют зеркало Maven Central и у них нет JCenter. Потом детально изучу их юз кейс и сделаю обзор.

А некоторые комментаторы пусть продолжают думать что они самые умные на свете и всё знают.


Кстати, что помешало сделать groovy зависимостью bobbin? Чтобы не приходилось добавлять в зависимости и то и то.


Глупости! Надо cделать bobbin зависимостью groovy.
13 авг 19, 09:40    [21947709]     Ответить | Цитировать Сообщить модератору
 Re: Новый альтернативный Slf4j логгер Бобина  [new]
mayton
Member

Откуда: loopback
Сообщений: 41377
Lelouch
mayton
Корпораций?


Google, Apple и Oracle.
И даже Тим Кук сказал «It’s a revolution, Mayton»

Ну дай бох.
13 авг 19, 09:50    [21947718]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: 1 2 3 4 5 6 7 8 9 10 11      [все]
Все форумы / Java Ответить