Как выполнить вход в OpenEdge Progress?

#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" ).