Показать сообщение отдельно
Старый 03.06.2018, 09:15   #1  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,275 / 3476 (122) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Стек вызовов в инфологе в D365FO
Всем добрый день!
На этом форуме уже несколько раз пролетала мысль про добавлении стека вызовов в инфолог (об этом упоминали разные авторы, и даже когда-то я в древности), но до версии D365FO еще не доходили. Я помню, как стек вызовов прикрутил к инфологу еще в 3.0, затем пришлось модификацию немного поменять, т.к. в 4.0 ввели упаковку данных инфолога в контейнер. Но зато в 2009 и особенно в 2012 модификация перетекла достаточно легко. Главной ее сложностью (в моем исполнении) была необходимость правки формы инфолога и класса Info, в результате чего при неаккуратной правке могло поломаться приложение. Это в общем-то основная причина, по которой я не выкладывал (и не выкладываю) ее на форум. Однако в версии D365FO, в связи с появлением понятия модели и пакета (Package), в котором создается модель – стало возможно эту модификацию сделать достаточно безопасной для инсталляции, хотя, к сожалению и пришлось немного пожертвовать удобством использования (в связи с запретом оверлеинга).

Соответственно, получилось нечто, что в целом (лично для меня) приносит больше пользы, чем вреда ). Ее еще можно дошлифовывать, но в неком «грубом представлении» вполне уже можно использовать в работе. Вполне вероятно – ошибки будут – поэтому просьба сообщать – буду править по мере сил и возможностей. Сразу скажу – разработка по времени еще не много обкатывалась, поэтому возможны какие-то недочеты, соответственно, тех, кто будут пользоваться прошу выдавать замечания – будем исследовать что можно будет сделать в разных ситуациях.

Для начала хочу сказать, что Microsoft решил «развести» уровни отображения сообщений и поэтому часть сообщений выводится на полоске при форме (в контексте формы), а часть – в верхнем меню системы. И даже об этом целых 2 странички написал в документации https://docs.microsoft.com/en-us/dyn...er-bar-details
https://docs.microsoft.com/en-us/dyn...messaging-user

Microsoft всем рекомендует использовать функции класса Message со словами, что старые добрые методы info/warning/error «Все еще поддерживаются». Логично – эти методы чуть ли не в каждом объекте, содержащем X++ написаны. Памятуя историю с устареванием RunBase в 2012 и его «возрождением» в D365FO )) – надеюсь, что в ближайшее время метод \Info\add (ну или любой его аналог, как центр сбора сообщений) не исчезнет, метод xSession::xppCallStack (или любой его аналог) тоже пока останется – ну и значит какое-то время мы сможем воспользоваться их интеграцией.
Чтобы было понятно - приведу текст класса Message (он небольшой)
X++:
public static class Message
{
    static int64 Add(MessageSeverity severity, SysInfoLogStr txt)
    {
        return infolog.insertMessage(severity, txt);
    }

    static int64 Remove(int64 messageId)
    {
        return infolog.removeMessage(messageId);
    }
}
И метод insertMessage (я пока вырезал закомментаренный код)
X++:
    int64 insertMessage(
        MessageSeverity severity,
        str _txt,
        str label = '')
    {
        int actionClassId;
        container packedAction;
        
        Exception exception;
        switch(severity)
        {
            case MessageSeverity::Informational:
                exception = Exception::Info;
                break;
            case MessageSeverity::Warning:
                exception = Exception::Warning;
                break;
            default:
                exception = Exception::Error;
                break;
        }

        if (!this.shouldAdd(exception))
        {
            return 0;
        }

        // Raise the message event if there are consumers and the event capturing is enabled
        if (enableMinimumLevelInfologRaiseMessageEvent && (exception >= minimumLevelInfologRaiseMessageEvent))
        {
            this.onMessageAdd(exception, _txt);
        }
        return super(severity, getprefix()+_txt, this.GetLabelContext(_txt));
    }
Ну т.е. мы видим, что класс Message хоть и обходит в явном виде \Info\add - все равно есть возможность встроиться в делегат OnMessageAdd, который также вызывается и из \Info\add.

На него можно подписаться и т.о. получить информацию о сообщении. Правда этот делегат был сделан исключительно для запуска тестов и для того, чтобы воспользоваться надо в классе Info включить режим сбора событий (можно посмотреть ссылки на этот метод). Но этот режим влияет исключительно только на возможность подписки на этот делегат (опять-таки- смотрим код), поэтому в целом мы для себя вполне можем его использовать.

Соответственно, при реализации стека вызовов в инфологе глобально была применена идея включения режима перехвата событий, перехват событий и запись их с добавлением информации по стеку вызовов (стек вызовов я не очищал от вызова непосредственно перехватчика – лично меня эта строчка не напрягает, а все желающие могут если захотят сами это доделать).
Заодно решилась проблема чтения длинных соообщений в инфологе, текст которых в полоске на форме был неудобочитаем (по крайней мере для меня).

Соответственно, как работает моя модификация:
1. В параметры пользователя добавлен флажок «Стек вызовов». Включение флажка включает режим логирования сообщений инфолога. Логируется только то, что проходит через \Info\add. Соответственно, бывают ситуации, когда сообщения не залогировались, -но я пока не отловил эти ситуации. Выключение флажка очищает лог текущего пользователя. В роли лога выступает обычная таблица в БД. Пользователи разделяются в ней по полю CreatedBy.
2. При помощи делегата OnMessageAdd сообщения собираются в таблицу лога (Лог чистится только при выключении флажка у пользователя. Я пытался его очищать на событии OnClear у инфолога – пока это не дало результата. Соответственно, если будут какие-нибудь предложения / мысли на эту тему – с интересом ознакомлюсь).
3. Данные таблицы лога отображаются на форме. Форма вызывается с вкладки OPTIONS (ПАРАМЕТРЫ), которая является общей для почти всех форм в D365FO (за исключением диалоговых и может еще каких-нибудь сильно специализированных). При отключенном флажке у пользователя – вызов формы стека вызовов не показывается на этой вкладке (чтобы не смущать пользователей системы), поэтому после включения флажка в параметрах пользователя – нужно открыть какую-нибудь форму с вкладкой ПАРАМЕТРЫ для вызова формы лога стека вызовов.
4. Делегат OnMessageAdd работает только для роли «Системный администратор», поэтому для возможности собрать стек вызовов для пользователя без этой роли я добавил в модификацию специальную роль CallStack, а в коде пришлось временно (в момент включения режима сбора сообщений) обмануть функцию Global::isSystemAdministrator(), заставив временно ее вернуть истину на момент включения режима и «вернуть как было» после момента включения режима.
Меточный файл не делал, хватило стандартных существующих меток.
Прикладываю .axmodel-файл и .axpp-файл

Нажмите на изображение для увеличения
Название: SNAG_Program-0058.png
Просмотров: 603
Размер:	32.8 Кб
ID:	11934

Нажмите на изображение для увеличения
Название: SNAG_Program-0054.png
Просмотров: 567
Размер:	44.1 Кб
ID:	11935

Нажмите на изображение для увеличения
Название: SNAG_Program-0056.png
Просмотров: 580
Размер:	47.1 Кб
ID:	11936

Нажмите на изображение для увеличения
Название: SNAG_Program-0057.png
Просмотров: 559
Размер:	63.2 Кб
ID:	11937

CallStack-VSUH.axmodel
CallStack.axpp
__________________
Возможно сделать все. Вопрос времени

Последний раз редактировалось sukhanchik; 03.06.2018 в 13:41.
За это сообщение автора поблагодарили: skuull (2), raz (10), EVGL (10), AlexSD (4), trud (5), mazzy (10), axotnik88 (1), Logger (15), Jorj (1), gl00mie (10), ice321i (1).