lgwillmore / warden

Kotlin Attribute Based Access Control
MIT License
19 stars 3 forks source link

Improve debugging support - decision evaluation tracing #25

Open lgwillmore opened 3 years ago

aSemy commented 2 years ago

I saw a relevant blog post today: https://publicobject.com/2022/05/01/eventlisteners-are-good/

Here are the key snippets

[W]e created an abstract class with functions for each of our would-be log statements:

abstract class EventListener {
  open fun callStart(call: Call) {}
  open fun callEnd(call: Call) {}
  open fun callFailed(call: Call, ioe: IOException) {}
  open fun dnsStart(call: Call, domainName: String) {}
  open fun dnsEnd(call: Call, domainName: String, list: List<InetAddress>) {}
  ...
}

...

EventListener Recipe

If you wanna do an event listener in your library or app, here’s what I’ve done:

  1. Create an abstract class EventListener. I prefer an abstract class over an interface here ’cause I want to introduce new functions in library upgrades without breaking compatibility.
  2. Create a value EventListener.NONE that is the no-op EventListener. This makes a nice default.
  3. Create a pair of functions for important long-running operations. For example, OkHttp has dnsStart() and dnsEnd(). Include relevant data as arguments! In OkHttp we were a bit too conservative in what we passed to these functions; given a do-over I would have added more information.
  4. Create functions for stuff that can fail, like callFailed(). In OkHttp we don’t always call the end callback if the operation fails.
  5. Create functions for other interesting things that happen in your library! In OkHttp we have events like cacheHit() and cacheMiss(), and metrics systems can use this to create line charts showing cache effectiveness.
lgwillmore commented 2 years ago

Ya, a bit visitor patterny. Nice clean decoupled approach. But in my head I was imagining the output to be a nicely nested tree structure of the policy evaluations - event listener might not be able to produce something like that... will have to think about it. start and end events help, or have to pass some sort of depth parameter around.

Going to start work on this one soon though - very important for ease of use I think