模式匹配规则引擎应使用什么模式或方法

时间:2017-10-20 06:54:36

标签: design-patterns matching rule-engine

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

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

- )ErrorID:唯一

- )ErrorType:可能太快"例如

- )到达:发生错误时

- )结束:错误结束时

- )速度,热量,......:例如。 100km / h和100度。

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

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

例如.1)如果消息x在特定时间间隔内出现y次,我想找到它(不管其他消息如何)

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

例如.3)y类型的x个messeges具有相同的时间戳,我想找到它们

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

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

任何有关良好方法的建议都可以捕获此问题(没有软件,我想自己编写代码)?

2 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

模式

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

由于您有一个要处理的大文件,我认为您无法将其放入内存中。虽然你可以使用一个天真的基于流的文件阅读过程,但它似乎限制在这里。如果你决定为你的代码最好能够读取文件start-to-end 并偶尔返回(对于子问题#1),我实现了一个自定义的{{3封装了这个逻辑。这不是一个只从开始到结束的正常迭代器,因此除first()next()isEndReached()函数外,反向需要一组类似的函数迭代(previous()isBeginningReached(),也许last())。

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

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

算法和方法

  

如果消息x在特定时间间隔内出现y次,我想找到它(不管其间的其他消息)

在我看来,使用算法很难解决这类问题。更重要的是,想要在将来搜索完全不同的内容。所以,我不会试图对所有那些做这项工作的自定义Macthers进行硬编码。

相反,我会将LogEntry集合存储到SQL数据库中。为什么这样?在这样做之后,您可以以您未想到的方式轻松有效地查询这些数据。编写SQL查询很容易,编写一个新的匹配器并不容易,它可以回溯大量的记录,对吧?这实际上不是我自己的想法 - 这就是我为一个巨大的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