【问题标题】:What is an effective way to track, identify and report every 'error message' raised by your application?什么是跟踪、识别和报告应用程序引发的每条“错误消息”的有效方法?
【发布时间】:2010-07-12 21:41:33
【问题描述】:

在案例管理和工作流系统中,这似乎出现了很多。需要提供“系统”中每个业务消息的完整列表,并提供其可能的原因和纠正措施。

供应商的例子是 Oracle:他们的所有错误都有一个命名约定(例如 ORA-00237),并且他们记录了所有可能的 ORA-XXXXX 错误。

您如何在开发过程中“强制”执行此操作,而又不会给团队造成过度负担?问题域的示例是贷款申请、公司税务准备申请、权利计划的资格确定等软件。

【问题讨论】:

  • 我不确定我是否跟随。您是否将 ORA-00237 称为一个特别有用的特定 Oracle 错误?或者您是否使用 ORA-00237 作为 Oracle 一般如何报告错误的一般示例?
  • ORA-00237 错误代码只是一个例子。一个试图列出所有 Oracle 错误代码的站点是ora-code.com。如果您的业务逻辑使用 Java 或 C#,并且您有类似的需求来识别所有可能的业务逻辑错误/警告,那么从技术角度来看,您将如何处理。此外,您如何在开发过程中“强制”执行此操作,而不会给团队造成过度负担?示例问题域是贷款申请、公司税务准备申请、确定权利计划的资格等软件......

标签: c# java oracle error-handling


【解决方案1】:

对于您自己的应用程序引发的错误,一个常见的解决方案是有一个这样的错误消息表:

create table errors
    ( error_no integer primary key
    , error_text varchar2(200)
    , error_cause varchar2(4000)
    , error_action varchar2(4000)
    );

一个典型的条目可能是:

insert into errors (error_no, error_text, error_cause, error_action)
values (479, 'End date cannot be earlier than start date',
        'A start date and an end date were entered where the end date was before the start date, which is not allowed.',
        'Correct the start and end dates and retry.'
       );

然后在您的代码中处理类似这样的异常:

if p_start_date > p_end_date then
    error_pkg.raise_error (479);
end if;

这个包会做这样的事情:

procedure raise_error (p_error_no integer)
is
    l_text errors.error_text%type;
begin
    select error_text into l_text
    from   errors
    where  error_no = p_error_no;
    raise_application_error(-20001, l_text);
end;

最终用户会看到如下内容:

ERROR 479: End date cannot be earlier than start date

然后可以查找它以获取原因和操作详细信息。

更高级的版本将允许在消息中显示数据值,在错误文本中使用占位符,如下所示:

insert into errors (error_no, error_text, error_cause, error_action)
values (456, 'Invalid action code: [1]',
        'An invalid action was specified', 'Correct the action code and retry.'
       );

error_pkg.raise_error (456, p_act_code);

【讨论】:

  • 我已经成功使用了上述技术。但是我仍然很难在不去每个用例的情况下列出业务上下文。我开发了一个脚本来查找每个 'error_pkg.raise_error' 调用(即 USER_SOURCE)并提取 if 语句。我使用该输出作为起点。客户希望显示每条消息的列表和上下文,而无需单独查看每个用例。而且,坦率地说,我们的用例并没有“所有”信息。从开发人员的角度来看,有些“流氓”消息是有意义的,但不是“在用例中”。
  • 是的,这绝不是万无一失的。我发现最终某些开发人员找到了设置通用错误的理由,例如 (999, '[1]') 其中 [1] 是占位符,然后在调用中提供实际消息。然后出于不同的原因在整个应用程序中使用它 - 从而首先破坏了拥有表格的目标!
【解决方案2】:

这是对需求的合理总结吗?

  1. 所有发出的消息都标有一些唯一性。
  2. 唯一性独立于文本消息的国际化。
  3. 这些 un​​iquifier 会随着时间的推移保持稳定,新版本的应用程序应该使用相同的 uniquifier 来处理之前版本中发出的消息。这往往有助于建立民间传说:哦,是的,错误 ZZ-27B,这是由...引起的......
  4. 稳定性不受对文本的细微句法修复、拼写更正和消息阐述的影响。
  5. 我们需要帮助程序员做对。因此,我们希望尽可能让程序员轻松完成,并让代码审查员轻松验证。

在理想情况下,我想使用某种注释和/或注入技术来管理整个事情。但是,我想不出一种方法来确保 uniquifiers 随着时间的推移是稳定的,而无需开发人员参与。当开发人员重构某些代码、更改其位置时,修复文本中的一些错别字,发现它是“相同”的错误消息并非易事。

所以我会恢复我(非常)旧的做法:

1)。为 uniquifiers CCC-MM-nnn 设计一个合适的粒度。 CCC 是一个应用程序标识符,MM 一些“模块”可能比 Java 包层次结构的叶子更高。 nnn 是一个序列号。每个 MM 都有一个 Class,其中包含每个消息的静态常量。

// conceptually like this, but perhaps done with enums or annotations
static final MessageUniquifier  CCC_MM_123 = new MessageUniquifier("CCC_MM_123);

2)。有一个日志记录 api

Logger {
  public void logError(MessageUniquifier id, String message) ...

这种方法的效果是

  • 开发人员必须为每条消息提供一个 unquifier,否则编译错误
  • 创建新的唯一标识符的工作是编辑适当的唯一标识符类,我们有几个这样的编辑不会有太多争用。
  • 想出一个工具来检查没有两个消息生产点使用相同的唯一标识符是相对简单的。
  • 可以将每个错误的文档作为 java doc 添加到 uniquifier 类中,或者轻松匹配它们,因此很容易检查完整性。

【讨论】:

    猜你喜欢
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 2017-03-07
    • 2011-07-07
    相关资源
    最近更新 更多