#logging #openedge #progress-4gl
#ведение журнала #openedge #прогресс-4gl
Вопрос:
Я нашел разные способы регистрации чего-либо в процессе 4GL, но ни один из них не удовлетворяет:
У простого MESSAGE
оператора есть недостаток, заключающийся в том, что он очень плохо обрабатывает фреймы:
ON CHOOSE OF btn-Q4
DO:
MESSAGE "Line 1".
MESSAGE "Line 2".
MESSAGE "Line 3".
PROMPT-FOR ...
WITH FRAME ...
...
MESSAGE "Alert message" VIEW-AS ALERT-BOX.
PROMPT-FOR ...
WITH FRAME ... /* (another frame) */
...
MESSAGE "Another alert message" VIEW-AS ALERT-BOX.
...
MESSAGE "Normal message".
END.
Это начинается с отображения строк 1 и 2, для строки 3 есть полоса прокрутки, но она недоступна из-за других фреймов, похожих на диалоговые окна, и как только они исчезнут, исходных строк сообщений больше не будет.
Другой возможностью, уже показанной, является MESSAGE ... VIEW-AS ALERT-BOX
. Это работает нормально, и даже есть возможность копирования-вставки, но все сообщения отображаются в отдельных окнах предупреждений, что очень затрудняет обработку.
Третья возможность, упомянутая на этом сайте, — это использование менеджера журналов, но у меня нет файла, вызываемого *log*manager*
где-то при моей установке Progress 4GL, поэтому я не знаю, как это использовать.
Кто-нибудь может объяснить мне, как вести журнал? Чего бы я хотел, так это следующего:
...
LOG("Line1").
...
LOG("Line2").
...
LOG("Line3").
...
Отступ обозначает местоположение в стеке вызовов («Line3» вызывается функцией, в то время как «Line2» вызывается подфункцией, вызываемой подфункцией, вызываемой функцией).
Идея состоит в том, чтобы увидеть (в формате, доступном для копирования и вставки):
В идеале:
Line1
......Line2
..Line3
В случае, если это невозможно, я соглашаюсь на:
Line1
Line2
Line3
Знает ли anbody, существует ли это и как это реализовать?
Заранее спасибо
Ответ №1:
Если вы просто хотите записать несколько простых сообщений, вы можете перенаправить вывод в файл. Используйте OUTPUT TO
инструкцию с некоторыми сообщениями:
OUTPUT TO VALUE("logfile.txt").
PUT UNFORMATTED "Message 1" SKIP.
PUT UNFORMATTED "Message 2" SKIP.
PUT UNFORMATTED "Message 3" SKIP.
OUTPUT CLOSE.
Это создаст «logfile.txt «файл в вашей папке «Пуск». Он будет содержать следующее:
Message 1
Message 2
Message 3
PUT UNFORMATTED
Оператор отправляет строку в файл. SKIP
Ключевое слово добавляет перевод строки. OUTPUT CLOSE
Инструкция закрывает файл.
Если вы хотите добавить в существующий файл, используйте APPEND
OUTPUT
инструкцию on:
OUTPUT TO VALUE("logfile.txt") APPEND.
Комментарии:
1. Я поместил
OUTPUT TO VALUE("C:Temp_Folderlogfile.txt"). /* DDES */
в начало своего основного блока, но я получаю ошибку 602 «Вы помещаете метку в середину блока. Метки можно размещать только в начале блока. «. Что это значит и как я могу этого избежать?
Ответ №2:
Взгляните на документ о ведении журнала, особенно на LOG-MANAGER
команду и 4GLTrace
тип записи в журнале.
LOG-MANAGER
в целом это очень полезно для информации типа «system» — доступно много данных для отслеживания и отладки. Его также можно использовать для ведения журнала приложений с WRITE-MESSAGE
помощью метода; хотя это работает, это довольно грубо, и поэтому вам, вероятно, придется написать оболочку вокруг него, если вы хотите его использовать (например, для фильтрации уровней ведения журнала).
Если вы используете достаточно свежую версию, вы можете посмотреть https://docs.progress.com/bundle/openedge-abl-develop-services/page/ABL-application-logging.html который предоставляет оболочку для этого (и многого другого).
Комментарии:
1. У меня также нет файла с именем «4GLTrace» на моем компьютере.
2. Регистратор «LoggerBuidler» доступен только в версии 11.6.4 и далее. Документ о LOG-MANAGER (первая ссылка в моем ответе) описывает, как его использовать.
Ответ №3:
Простая библиотека ведения журнала:
/* logger.p
*
* to instantiate:
*
* run logger.p persistent
*
* three ways to call it from your code:
*
* publish "logMsg" ( msgLevel, messageText ). // requires no knowledge in the caller, no error if logger.p has not first been run persistently
* run doLogMsg ( msgLevel, messageText ). // requires no knowledge in the caller, error if logger.p is not run first
* logMsg( msgLevel, messageText ). // requires forward declaration in the caller
*/
subscribe to "setLogName" anywhere run-procedure "setLogName".
subscribe to "logMsg" anywhere run-procedure "doLogMsg".
define variable logMsgLevel as integer no-undo initial 3.
define variable logMsgFileName as character no-undo initial "application.log".
define stream logStream.
/* install self as a session super-procedure
*/
session:add-super-procedure( this-procedure ).
return.
/* housekeeping
*/
procedure setLogName:
define input parameter logName as character no-undo.
logMsgFileName = logName.
return.
end.
procedure setLogLevel:
define input parameter logLevel as integer no-undo.
logMsgLevel = logLevel.
return.
end.
/* to use this function directly from another procedure you must first declare it in that procedure:
*
* function logMsg returns logical ( input msgLevel as integer, input msgText as character ) in super.
*/
function logMsg returns logical ( input msgLevel as integer, input msgText as character ):
run doLogMsg( msgLevel, msgText ).
return true.
end.
/* procedures do not need to be forward declared but we can not have a function and a procedure with the same name
*/
procedure doLogMsg:
define input parameter msgLevel as integer no-undo.
define input parameter msgText as character no-undo.
if msgLevel <= logMsgLevel then
do:
output stream logStream to value( logMsgFileName ) append.
put stream logStream unformatted today " " string( time, "hh:mm:ss" ) " " msgText skip.
output stream logStream close.
end.
return.
end.
Примерный тестовый стенд:
/* test logger.p
*/
/* run doLogMsg ( 3, "test a" ). */
/* logMsg( 3, "test b" ). */
function logMsg returns logical ( input msgLevel as integer, input msgText as character ) in super. /* usually this is in a include file in the procedure header */
publish "logMsg" ( 3, "test 1" ).
run ./logger.p persistent. /* loads logger.p into memory... */
run setLogName ( "test.log" ).
publish "logMsg" ( 3, "test 2" ).
run doLogMsg ( 3, "test 3" ).
logMsg( 3, "test 4" ).