Search code examples
kotlinaopnewrelic

How to do method instrumentation in Kotlin - but keep it method testable


I have a method that I need to instrument to call New Relic: setup a segment, run the business logic and end the segment. Is there a way to do it in Kotlin (as in Spring AOP)?

fun saveCustomer() {
   val segment = NewRelic.getAgent().transaction.startSegment("save customer")
   // business logic here
   segment.end()
}

I experimented isolating newRelic dependency and can now reuse it across my whole app:

fun saveCustomer() {
   newRelic.executeWithSegment { // this starts/ends the segment and calls the function block
      // business logic here
   }
}

However, this makes unit testing of saveCustomer harder, because after mocking newRelic.executeWithSegment (which I must; otherwise New Relic is contacted in the tests), the code block (business logic) is not executed anymore - so the test fails.

Is there a way to fulfill those requirements? (Perhaps with an annotation or using Kotlin delegation pattern or even some lightweight library; not sure.)


Solution

  • You can use AspectJ.

    • It is independent of Spring, more powerful and more efficient (no proxies) than Spring AOP.
    • It should work with any JVM language, although I never tried with Kotlin as a target for my aspects.
    • If you do compile-time weaving, the AspectJ runtime is the only dependency you need. Its size is 120K.
    • For load-time weaving you need the AspectJ weaving agent instead. Its size is 1.9M.