【问题标题】:What pattern or approach should be used for a pattern matching rules engine模式匹配规则引擎应该使用什么模式或方法
【发布时间】:2017-10-20 06:54:35
【问题描述】:

我正在为以下问题寻找合适的方法/方法/模式: 我有一个长日志文件,其中包含存储在关系数据库表中的错误消息(errorID、errortype、错误开始和结束的时间戳,以及有关错误的其他信息)。错误消息,即。一个日志条目,可能有这样的标题:

[ErrorID,Errortype,到达,结束,速度,热量,...]

-) 错误ID:唯一

-) ErrorType: 例如可能是“太快”

-) 到达:错误发生时

-) 结束:当错误结束时

-) 速度,热量,...:例如。 100 公里/小时和 100 度。

可能还有其他字段,但请保持简单。附加字段只是提供有关错误的更多信息。

这些行/错误消息中的大多数都不重要,但某些消息组合很重要,假设有 100 种错误消息模式很重要(时间方面和消息内容方面),例如:

eg.1) 如果消息 x 在某个时间间隔内出现 y 次,我想找到它(无论中间的其他消息如何)

eg.2) 消息 z 本身很重要,我想找到它

eg.3) x 类型为 y 的消息块具有相同的时间戳,我想找到它们

这本质上是模式匹配,其中模式的每次出现都将返回 patternID 和模式中第一条消息的时间戳(或所有消息的时间间隔)。我可以为我想要找到的每种模式使用大量 if 语句轻松编写代码(例如,过滤日志并显示是否找到了某些东西),但这不可扩展并且很快就会变得混乱。

Factory+AbstractFactory-pattern 将是我的第一种方法(一般模式类型的抽象,特定实现的普通工厂),但我需要为每个模式创建一个工厂,并且只创建数百个类,类似地策略模式。我还发现有些东西叫做规则引擎,但我发现它们不够灵活,无法轻松捕捉我的问题。

有什么好的方法可以解决这个问题(没有软件,我想自己编写代码)?

【问题讨论】:

  • 1.更准确地描述您的数据文件(标题和示例数据)
  • 2.如果您有 3 个不同的问题,请从这个问题中提出 3 个不同的问题
  • 3.通常尝试更精确,更少冗长。想象一下,您在这里与编码机器交谈,它们需要输入来解决单个、精确指定的编码问题。不要在这里与人类交谈一段时间,让他们慢慢理解你想要什么,然后在某个时候他们开始解决你的问题,你回顾他们并告诉他们他们是否误解了你等等。
  • @hoijui:我更新了问题以包含日志表的示例标题。这基本上是一个问题:如何管理和检测特定日志消息类型的各种组合,这些组合可能会随着时间的推移而分布在大型日志表中。

标签: design-patterns matching rule-engine


【解决方案1】:

您可以查看Strategy 设计模式,它应该可以帮助您将规则实现为具有统一界面的不同策略。

现在您可以逐一阅读日志消息并传递给所有规则。您可以检查Chain of responsibility 模式,特别是如果相同的日志消息可以触发不同的规则并且您想避免这种情况。链或责任可以让您按优先级顺序您的规则,因此当触发更重要的规则时,它会停止沿链传递消息。

我没有看到抽象工厂在这里是如何适用的,也许你没有提供足够的细节。 Abstract Factory 旨在创建一个相关对象的家族,而您的rules 不是这样的家族,它们是同一抽象对象的不同实现,rule

【讨论】:

    【解决方案2】:

    模式

    如果我是你,我会使用以下模式组合专门用于数据预处理

    由于您有一个大文件要处理,我假设您无法将其放入内存中。虽然您可以使用简单的基于流的文件读取过程,但这似乎是有限的。如果您决定对于您的代码,最好能够从头到尾读取文件偶尔返回(对于子问题 #1),我将实现一个自定义 Iterator 来封装这个逻辑。不会是只从头到尾进行的普通迭代器,因此除了first()next()isEndReached() 函数之外,还需要一组类似的函数用于反向迭代(previous()isBeginningReached(),也许还有last())。

    当迭代器访问行日志条目时,它需要在LogEntry 对象中解析它们。根据行格式的复杂程度和稳定性,您可能希望使用简单的Factory 或更灵活的Builder,甚至是重型解析器(Interpreter)。

    然后可以通过拥有一组匹配器来解决最微不足道的问题,每个匹配器检测属于特定感兴趣类别的条目。在最简单的实现中,这样的模式可能是一个接受LogEntry 对象的简单谓词。

    算法和方法

    如果消息 x 在某个时间间隔内出现 y 次,我想找到它(无论中间的其他消息如何)

    在我看来,这类问题很难用算法解决。更重要的是,您将来想要搜索完全不同的东西。所以,我不会尝试对所有这些自定义 Macthers 进行硬编码。

    相反,我会将LogEntry 集合存储到SQL 数据库中。为什么这样?之后,您可以以您从未想过的方式轻松高效地查询这些数据。编写 SQL 查询很容易,编写一个新的 Matcher 来回溯并强制遍历大量记录并不容易,对吧?这实际上不是我自己的想法——当我为一个巨大的 IT 怪物工作时,我们就是这样做的。

    所以,回到最初的问题 #1,最终的解决方案可能看起来就这么简单

    SELECT Message, COUNT(Message)
    FROM LogEntries
    WHERE
      '2017-01-01T00:00:00' >= TimeStamp AND TimeStamp <= '2017-01-02T00:00:00'
    GROUP BY
      Message
    HAVING
      COUNT(Message) > 5
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-17
      • 2022-11-10
      • 2010-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多