如何登录 OpenEdge Progress?

问题描述

我发现了在 Progress 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。这很好用,甚至还有复制粘贴的可能,但是所有消息都显示在单独的警报框中,这使得处理起来非常困难。

本网站上提到的第三种可能性是使用日志管理器,但我在 Progress 4GL 安装的某处没有名为 *log*manager*文件,所以我不知道如何使用这个。

谁能解释我如何进行日志记录?我想要的是以下内容

...
LOG("Line1").
...
      LOG("Line2").
...
  LOG("Line3").
...

缩进代表在调用栈中的位置(“Line3”被函数调用,而“Line2”被子函数调用,被子函数调用,被函数调用)。

这个想法是(以可复制粘贴的格式):

理想情况下:

Line1
......Line2
..Line3

如果这是不可能的,我就满足于:

Line1
Line2
Line3

有人知道这是否存在以及如何实现吗?

提前致谢

解决方法

查看有关日志记录的 doc,尤其是 LOG-MANAGER 命令和 4GLTrace 日志条目类型。

LOG-MANAGER 通常对于“系统”类型信息非常有用 - 有很多跟踪和调试数据可用。它还可以通过 WRITE-MESSAGE 方法用于应用程序日志记录;虽然这很有效,但它非常粗糙,因此如果您想使用它(例如,用于过滤日志级别),您可能必须围绕它编写一个包装器。

如果您使用的是相当新的版本,您可以查看 https://docs.progress.com/bundle/openedge-abl-develop-services/page/ABL-application-logging.html,它为此(以及更多)提供了一个包装器。

,

如果您只想记录一些简单的消息,您可以将输出重定向到一个文件。对一些消息使用 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

OUTPUT TO VALUE("logfile.txt") APPEND.
,

一个简单的日志库:

/* 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" ).