R – Where to put auditing or logging

asp.net-mvcloggingnhibernate

I'm currently working on an ASP.NET MVC project using NHibernate and I need to keep track of changes on some entities in order to be able to make some reports and queries over the data. For this reason I wanted to have the data in a table, but I'm trying to decide where to "hook" the auditing code.

On the NHibernate layer:

  • PRO: Powerful event system to track any change
  • PRO: Nothing can be changed in the application without notice (unless someone uses raw SQL…)
  • CON: As I have a generic repository… then I have to filter out the useful entities (I don't need to track everything).
  • CON: I don't have easy access to the controller and the action so I can only track basic operations (update, delete…). I can get the HttpContext at least to get some info.

On an Action Filter at Controller level:

  • PRO: Full information on the request and web application status. This way I can distinguish an "edit" from a "status change" and be more descriptive in the audit information.
  • CON: Someone can forget a filter and an important action can be taken without notice which is a big con.

Any clue?

Update: See how to Create an Audit Log using NHibernate Events.

Best Answer

I think doing this at the repository level is a much better fit. Mostly because you may, in the future, decide to add some method of access to your repository which does not go through MVC (e.g., a WCF interface to the data).

So the question becomes, how do you address the cons you've listed about doing it on the NHibernate layer?

Filtering out the useful entities is simple enough. I would probably do this via a custom attribute on the entity type. You can tag the entities you want to track, or the ones you don't; whichever is easier.

Figuring out what the controller really intended is harder. I'm going to dispute that you can "get the HttpContext"; I don't think it is a good idea to do this in a repository, because the separation of concerns. The repository should not be dependent on the web. One method would be to create custom methods on the repository for actions you'd like to track differently; this is especially attractive if there are other aspects of these edits which behave differently, such as different security. Another method is to examine the changes by comparing the old and new versions of the objects and derive the actual nature of the change. A third method is to make no attempt to derive the nature of the change, but just store the before and after versions in the log so that the person who reads the log can figure it out for themselves.