0

I'm working on a greenfield Web API and need to log users' actions in a friendly way. I can see its easy to gather the logged in user, the controller, the action, and parameters like this post What I am looking for is away to give human readable friendly messages like:

  • "Paul Logged in" + timestamp
  • "Paul Created a new product (some product metadata)" + timestamp
  • "Paul Deleted Product xyz" + timestamp

I could adapt the answer here and then use a lookup table on the controller and action to translate to my human readable string with some token replacements but I can see that being a maintenance overhead when new actions are added. It also means a developer might forget to put the call in and we miss auditing.

Is there a way I can use an annotation on the action to specify what my human readable log message will be? (possibly with tokens) Has anybody done this in a generic manner without the code becoming totally custom to that application?

Community
  • 1
  • 1
Paul
  • 1,483
  • 14
  • 32

2 Answers2

1

I would look into an Aspect oriented programming framework to cross cut your application in a way that's maintainable. Having a strong typed annotation on every action specific to a logging mechanism will be readable and maintainable provided you are happy that to add a the logging capability, you will require a re-compilation. You could switch these on or off using a config setting easily.

I have used and would recommend PostSharp here, its awesome and free (for basic aspects).

A good example is:

http://doc.postsharp.net/example-trace

I have implemented a modified version of this with log4net and it works really well in a production environment.

Generally speaking i am not a fan of AOP as its surprise factor can be disconcerting, but in cases like this the maintenance overhead reduction is worth the trade off.

Paul
  • 1,483
  • 14
  • 32
KnowHoper
  • 4,352
  • 3
  • 39
  • 54
1

I think that trying to accomplish this at the UI layer is the wrong place. If I hit the url foo.com/product/delete/1 does that mean that I deleted the product? I would say no.

  • What happens if that user didn't have permission?
  • What happens if the product didn't exist?
  • What happens if the product failed to delete?

I think the correct place to do this kind of auditing is at the repo layer of your code. Have a method something like this:

public void DeleteProduct(int productID, string username) {
   _db.Products.Delete(productID); //pseudo code
   _auditService.AddAuditRecord($"Product ID {productID} was deleted by {username}");
}

This way, you only audit the data change if it was successful.

jhilden
  • 12,207
  • 5
  • 53
  • 76
  • Some good points to consider @jhilden. The benefit of logging in the API layer as I see it would be if we had a requirement to audit if a user tries to do something they're not authorized to. – Paul Apr 13 '16 at 07:38