【问题标题】:Appropriate design pattern for an event log parser?事件日志解析器的适当设计模式?
【发布时间】:2010-09-10 18:49:23
【问题描述】:

处理一个解析事件日志的项目,然后根据这些事件的属性更新模型。我对“完成它”非常懒惰,更关心前期优化、精简代码和正确的设计模式。主要是自学实验。我感兴趣的是更有经验的设计师认为哪些模式是相关的,或者哪种类型的伪代码对象架构是最好的、最容易维护的等等。

单个日志中可以有 500,000 个事件,大约有 60 种类型的事件,所有这些都共享大约 7 个基本属性,然后根据事件类型具有 0 到 15 个附加属性。事件类型是日志文件中每一行的第二个属性。

所以我尝试了一个非常丑陋的命令式解析器,它逐行遍历日志,然后逐行处理事件。然后我尝试了一个使用“nextEvent”模式的词法规范,该模式在循环中被调用并被处理。然后我尝试了一个简单的旧“解析”方法,它永远不会返回,只是将事件触发到注册的侦听器回调。无论事件类型如何,我都尝试了单个回调,以及特定于每种事件类型的回调方法。

我尝试了一个包含所有可能属性的基“事件”类。我试图避免“新事件”调用(因为可能有大量事件并且事件对象通常是短暂的),并且每种类型的回调方法都带有原始属性参数。我尝试为 60 种事件类型中的每一种都创建一个子类,并使用一个具有 7 个公共基本属性的抽象事件父类。

我最近尝试更进一步,并使用命令模式为每种事件类型放置事件处理代码。我不确定我是否喜欢这种方法,它与每种类型的回调方法是否真的相似,只是代码位于类型子类的执行函数中,而不是每种类型的回调方法。

问题是很多模型更新逻辑是共享的,而且很多是特定于子类的,我刚刚开始对整个事情感到困惑。我希望有人至少可以为我指明一个考虑的方向!

【问题讨论】:

    标签: java logging


    【解决方案1】:

    嗯...对于一件事,而不是具有所有属性的联合的单个事件类,或 61 个事件类(1 个基数,60 个子类),在具有如此多变化的场景中,我很想有一个事件类,它使用属性包(字典、哈希表、w/e 漂浮你的船)来存储事件信息。事件的类型只是放入包中的另一个属性值。我倾向于这种方式的主要原因只是因为我不愿意维护任何东西的 60 个派生类。

    最大的问题是...在处理事件时,您必须做什么。您是否将它们格式化为报告,将它们组织成数据库表,如果发生某些事件时唤醒人们......什么?

    这是一个事后分析器,还是一个实时事件处理程序?我的意思是,您是在事件进入时监控日志,还是只在第二天解析日志文件?

    【讨论】:

    • 好吧,我很确定我想坚持使用原语作为事件属性,因为它们是已知的且不变的,而且我非常关心性能。我想生成关于事件块的聚合信息的报告。事后,但我想按顺序处理(确定性?)。
    【解决方案2】:

    考虑一个策略对象的享元工厂,每个“类”事件一个。

    对于每一行事件数据,从享元工厂中查找合适的解析策略,然后将事件数据传递给策略进行解析。 60 个策略对象中的每一个都可以属于同一类,但配置有不同的字段解析对象组合。如果没有更多细节,要更具体有点困难。

    【讨论】:

    • 解析器组件已经完成,它是一个有限状态机,并且对所有事件都工作得很好。对不起,如果我不清楚。问题是我不知道如何处理解析后的事件。
    【解决方案3】:

    可能是Hashed Adapter Objects(如果你能在网上找到一个很好的解释 - 他们似乎缺乏。)

    【讨论】:

    • 我最终使用了类似的东西以及属性包方法。我基本上只是提取事件类型作为包的第二个属性,并将处理程序附加到 60 种不同的类型。感谢您的正式参考。
    【解决方案4】:

    就在顶部:

    我喜欢接受的答案中关于只有一个类具有属性映射的建议。我也认为行为也可以这样组装:

    class Event
    {
        // maps property name to property value
        private Map<String, String> properties;
    
        // maps property name to model updater
        private Map<String, ModelUpdater> updaters; 
    
        public void update(Model modelToUpdate)
        {
            foreach(String key in this.properties.keys)
            {
                ModelUpdater updater = this.updaters[key];
                String propertyValue = this.properties[key];
    
                updaters.updateModelUsingValue(model, propertyValue);
            }
        }
    
    }
    

    未显示 ModelUpdater 类。它根据属性更新您的模型。我组成了循环;这可能是也可能不是您的算法实际上是什么。我可能会让 ModelUpdater 更像一个界面。每个实现者都是每个属性,并会更新模型。

    那么我的“主循环”将是:

    Model someModel;
    
    foreach(line in logFile)
    {
        Event e = EventFactory.createFrom(line);
        e.update(someModel);
    }
    

    EventFactory 从文件构造事件。它根据事件的属性填充两个地图。这意味着有某种方法可以将属性与其关联的模型更新程序相匹配。

    我没有任何花哨的模式名称给你。如果您有一些复杂的规则,例如事件是否具有属性 A、B 和 C,则忽略 B 的模型更新器,那么必须以某种方式扩展此方法。最有可能的是,您可能需要使用规则对象模式以某种方式将一些规则注入 EventFactory。好了,有一个适合你的模式名称!

    【讨论】:

      【解决方案5】:

      我不确定我是否正确理解了这个问题。我假设有一个复杂的“模型更新逻辑”。不要通过 60 个类分发它,将其保存在一个地方,将其从事件类中移出(Mediator 模式之类的)。

      您的 Mediator 将使用事件类(我不明白您如何在此处使用享元),事件可以自行解析。

      如果更新规则非常复杂,您无法使用通用编程语言真正解决问题。考虑使用基于规则的引擎或类似的东西。

      【讨论】:

        猜你喜欢
        • 2022-12-28
        • 2017-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多