3

我很难为小型事件日志记录框架概念化一个理智的抽象,并且在野外没有遇到任何适用于此的可比较的东西。

概述:我们的 Web 应用程序需要从服务器端记录事件。事件数据经过 json 编码以写入平面文件。事件可能是页面浏览、注册、错误条件等。

所有事件都将包含一组核心数据,例如 Web 请求信息和会话状态。任何事件都应该能够定义要记录的附加数据。

理想情况下,触发事件的界面将非常小。事件定义和数据要求应在单个配置文件中定义。数据验证和数据转换应该隐藏在这个配置文件后面。换句话说,记录事件的接口应该只需要事件名称和要在事件中转换和记录的数据结构。

我最初的想法是,将单个数据结构映射到单个函数,其职责是将数据结构转换为字典,最终将合并到最终的事件对象中,然后进行 json 编码并写入文件。我将这些称为“作曲家”功能。在 Django 术语中,配置文件中的某些内容会映射,例如,传递给视图的 HTTP 请求对象到“request_composer”函​​数。该函数将构造一个从该请求对象中提取的数据字典。从视图发出的事件需要传入那个“请求”对象。

我想我的问题是,是否存在我忽略的模式或抽象可以干净地转换任意数据结构并将它们合并到最终数据结构中。我觉得这种“单一数据类型映射到单一转换函数”有点笨拙和不雅。当单个转换器接受多个参数是有意义的时,它也会崩溃。

4

2 回答 2

1

亚伦没有硬性规定。我的建议是你开始想象如果你有整个设计并且你想从一个视图中触发一个事件,那么实现会是什么样子。

所以这是我的建议,它有这些特定的目标:

  • 必须明确引用事件(Django 的设计)
  • 事件可以重复使用或特定于应用程序
  • 每个事件都需要一个请求实例
  • 每个事件都可以收集额外的任意参数或关键字参数,它们所要做的就是为事件处理器提供一个上下文
  • 事件处理器将提取请求数据,将其与上下文序列化为 JSON,并将其附加到日志文件

所以假设你在你的项目中创建了应用程序,myproj.events并且你有一些应用程序在myproj.myapp.

让我们在以下位置创建事件处理器和默认项目范围的实例myproj/events/__init__.py

import 

class Events(object): pass  # Use your imagination

events = Events(logfile=StringIO.StringIO)  # Say I wanted to log to a file-like object

您可以在单个模块myproj/myapp/events.py中配置所有特定于应用程序的事件:myproj.myapp

from myproj.events import events

@events.register_event
def view_requested(request)
    return request


@events.register_event
def user_signed_in(request)
    user = request.user
    return request, dict(username=user.username, gravatar=user.profile.gravatar)

然后在您的观点中,您可以:

from django.http import HttpResponse
from myproj.myapps import events


def foo(request):
    events.view_requested(request)
    return HttpResponse

这种方法从Django 的 Signals中获得了很多设计提示,它提供了一个直观的界面,通过简单地在发生的上下文中调用相关信号来重用接收器回调中隔离的行为。

实际上,我什至建议您查看它的实现,看看您是否可以实际使用或扩展它以满足您的特定需求。

于 2012-10-19T07:48:42.487 回答
1

这听起来很像 Facade(复杂实现的简单接口),可能与 Strategy(在运行时或配置/启动期间在进程的几个具体实现之间切换)和 Builder(提供一个复杂对象的通用抽象描述)结合策略可以转换为实际的表示)。您可能会发现,一旦使用了 Strategy,就没有必要使用 Facade。

http://en.wikipedia.org/wiki/Builder_pattern

http://en.wikipedia.org/wiki/Facade_pattern

http://en.wikipedia.org/wiki/Strategy_pattern

所以更具体一点:

Facade 将有两种方法:Log 和 SetLogger。

如果您使用 Prototype,您将有一个事件类型,以及事件的每个组件的类型。如果您有一个非常复杂的事件要记录,或者需要以几种非常不同的方式记录它,您只会使用 Prototype。

将有一个记录器(策略)的接口。这在外观中用于 SetLogger 方法。如果您使用 Prototype,Facade.Log 和 Logger.Log 的接口可能会有一个类似 log(PrototypeEvent e) 的方法。

按照下面的链接获取不使用原型但使用策略的简单记录器。这里没有 Facade,因为前端类实际上只跟踪当前记录器。

我将使用 C# 创建简单的记录器,那么我可以使用哪些设计模式来创建它作为最佳实践?

于 2012-10-19T06:42:32.883 回答